home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume89 / languags / zc.3 < prev    next >
Text File  |  1989-03-08  |  63KB  |  3,725 lines

  1. Path: xanth!lll-winken!csd4.milw.wisc.edu!mailrus!bbn!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v89i030:  zc - c compiler, Part03/04
  5. Message-ID: <12044@swan.ulowell.edu>
  6. Date: 8 Mar 89 03:04:10 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 3714
  9. Approved: page@swan.ulowell.edu
  10.  
  11. Submitted-by: monty@brahms.Berkeley.EDU (Joe Montgomery)
  12. Posting-number: Volume 89, Issue 30
  13. Archive-name: languages/zc.3
  14.  
  15. #    This is a shell archive.
  16. #    Remove everything above and including the cut line.
  17. #    Then run the rest of the file through sh.
  18. #----cut here-----cut here-----cut here-----cut here----#
  19. #!/bin/sh
  20. # shar:    Shell Archiver
  21. #    Run the following text with /bin/sh to create:
  22. #    gen.c
  23. #    gsub.c
  24. #    gunk.c
  25. #    main.c
  26. #    md.c
  27. #    nodes.c
  28. # This archive created: Tue Mar  7 21:50:03 1989
  29. cat << \SHAR_EOF > gen.c
  30. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  31.  *
  32.  * Permission is granted to anyone to use this software for any purpose
  33.  * on any computer system, and to redistribute it freely, with the
  34.  * following restrictions:
  35.  * 1) No charge may be made other than reasonable charges for reproduction.
  36.  * 2) Modified versions must be clearly marked as such.
  37.  * 3) The authors are not responsible for any harmful consequences
  38.  *    of using this software, even if they result from defects in it.
  39.  *
  40.  *    gen.c
  41.  *
  42.  *    Generate code.
  43.  *    Includes main routine and code generation for unary nodes
  44.  *    and leafs.
  45.  *   Revised: Dec 1988    Joe Montgomery
  46.  *
  47.  *   Revised gen.c to call externfunref to declare all functions XREF
  48.  *
  49.  *     other modules:
  50.  *   Revised main.c to use Amiga File System Naming Conventions
  51.  *    Added ?,C,F switches. ? help
  52.  *                  C force data,bss into Chip memory
  53.  *                  F force data,bss into Fast memory
  54.  *    To be added -o switch to specify assembly output
  55.  *   Revised out.c to use MOTOROLA assembly directives in order
  56.  *    to be compatible with C.Gibbs a68k assembler & blink
  57.  *    Added END statement
  58.  *    Changed .comm label,size to label DC.x 0
  59.  *   Revised d2.c so that externs are declared as XREF -----
  60.  *   Revised g2.c & gen.c to declare all called functions XREF
  61.  *     (will need to change this to declare only external functions)
  62.  *
  63.  *
  64.  *   All changes labeled JMM
  65.  *
  66.  */
  67.  
  68. #include <stdio.h>
  69. #include "param.h"
  70. #include "bstok.h"
  71. #include "tytok.h"
  72. #include "flags.h"
  73. #include "nodes.h"
  74. #include "gen.h"
  75.  
  76. NODEP strsave;
  77. int cctest;
  78. static int reserve;
  79. static int tmpused;
  80.  
  81. extern xflags[];
  82. #define debug xflags['g'-'a']
  83.  
  84. #define FAIL    0
  85. #define OKAY    1
  86.  
  87. #define isimmed(np)     ((np)->g_flags & IMMEDID)
  88. #define isareg(np)      ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
  89. #define isdreg(np)      ((np)->g_token == REGVAR && (np)->g_rno < AREG)
  90. #define istdreg(np)     ((np)->g_token == REGVAR && (np)->g_rno < DRV_START)
  91.  
  92. int cookflags[] = {
  93.     0,
  94.     NOVAL_OK|CC_OK|IMMA_OK,     /* FORSIDE */
  95.     IMMA_OK,            /* FORPUSH */
  96.     CC_OK,                /* FORCC */
  97.     IMMA_OK,            /* FORIMA */
  98.     0,                /* FORADR */
  99.     IMMA_OK,            /* FORINIT */
  100.     0,                /* IND0 */
  101.     0,                /* RETSTRU */
  102. };
  103.  
  104.  
  105.  
  106. extern NODE *blktab;
  107. extern nmerrors;
  108.  
  109. genx(np, cookie)
  110. register NODEP np;
  111. {
  112.     int rv;
  113.  
  114.     if (np == NULL) return;
  115.     if (nmerrors)
  116.         goto bad;
  117.     if (debug) {
  118.         printf("GEN enter");
  119.         printnode(np);
  120.     }
  121.  
  122.     untype(np);
  123.     if (debug>1) {
  124.         printf("after UNTYPE");
  125.         printnode(np);
  126.     }
  127.  
  128.     tmpused = 0;
  129.     gunk(np);
  130.     if (tmpused && tmpused > blktab->b_tsize)
  131.         blktab->b_tsize = tmpused;
  132.     if (debug > 1) {
  133.         printf("after gunk");
  134.         printnode(np);
  135.     }
  136.     order(np);
  137.  
  138.     reserve = 0;
  139.     rv = eval(np, cookie);
  140.     if (rv == OKAY && debug) {
  141.         printf("GEN exit");
  142.         codeprint(np);
  143.     }
  144.     if (rv == OKAY)
  145.         rv = cookmon(np, cookie);
  146.     else
  147.         error("couldnt eval node");
  148.     freenode(np);
  149.     return rv;
  150. bad:
  151.     freenode(np);
  152.     return FAIL;
  153. }
  154.  
  155. eval(np, cookie)
  156. register NODEP np;
  157. {
  158.     int rv;
  159.  
  160.     np->g_r1 = np->g_r2 = -1;
  161.  
  162.     if (np == NULL) return FAIL;
  163.  
  164.     switch (np->g_type) {
  165.  
  166.     default:
  167.         rv = b_eval(np, cookie);
  168.         /* already did freetmps */
  169.         free1(np, np->n_left);
  170.         free1(np, np->n_right);
  171.         break;
  172.  
  173.     case EV_LEFT:
  174.         rv = u_eval(np, cookie);
  175.         freetmps(np);
  176.         free1(np, np->n_left);
  177.         break;
  178.  
  179.     case EV_NONE:
  180.         rv = l_eval(np);
  181.         break;
  182.     }
  183.     return rv;
  184. }
  185.  
  186. u_eval(np, cookie)
  187. register NODEP np;
  188. {
  189.     int subcook = FORADR;
  190.  
  191.     switch (np->g_token) {
  192.     case STAR:
  193.         subcook = FORIMA;
  194.         break;
  195.     case '!':
  196.         subcook = FORCC;
  197.         break;
  198.     }
  199.  
  200.     if (eval(np->n_left, subcook) == FAIL)
  201.         return FAIL;
  202.     return u_sube(np, cookflags[cookie]);
  203. }
  204.  
  205. u_sube(np, flags)
  206. register NODEP np;
  207. {
  208.     register NODEP lp = np->n_left;
  209.     long offs;
  210.     int i;
  211.  
  212.     switch (np->g_token) {
  213.     case '.':
  214.         if (np->g_fldw)
  215.             return fldget(np, flags);
  216.         offs = np->g_offs;
  217.         inherit(np);
  218.         np->g_offs += offs;
  219.         return OKAY;
  220.     case STAR:
  221.         if (isimmed(lp)) {
  222.             inherit(np);
  223.             np->g_flags &= ~IMMEDID;
  224.         } else if (isareg(lp)) {
  225.             indir(np, lp->g_rno);
  226.         } else {    /* NEED A temp */
  227.             if (lp->g_token == OREG && istemp(lp->g_rno))
  228.                 i = lp->g_rno;
  229.             else
  230.                 i = ralloc(AREG);
  231.             addcode(np, "\tmove.l\t<A,R0\n");
  232.             indir(np, i);
  233.         }
  234.         return OKAY;
  235.     case UNARY '&':
  236.         if (isimmed(lp))
  237.             warn("& ignored");
  238.         else if (lp->g_token == REGVAR)
  239.             return FAIL;
  240.         inherit(np);
  241.         np->g_flags |= IMMEDID;
  242.         if ((flags & IMMA_OK) == 0)
  243.             imm_oreg(np);
  244.         return OKAY;
  245.     case '~':
  246.         utemp(np);
  247.         addcode(np, "\tnot.S\tA\n");
  248.         cc_hack(np);
  249.         return OKAY;
  250.     case UNARY '-':
  251.         utemp(np);
  252.         addcode(np, "\tneg.S\tA\n");
  253.         cc_hack(np);
  254.         return OKAY;
  255.     case TCONV:
  256.         castgen(np);
  257.         return OKAY;
  258.     case PUSHER:    /* must not be on left of assign or asn-op */
  259.         if ((lp->g_token != OREG && lp->g_token != REGVAR) ||
  260.             istemp(lp->g_rno) == 0) {
  261.             inherit(np);
  262.             return OKAY;
  263.         }
  264.         addcode(np, "\tmove.S\t<A,-(sp)\n");
  265.         return OKAY;
  266.     case '(':
  267.         if (np->g_ty == ET_A) {         /* struct returned */
  268.             frc_ral(AREG);
  269.             indir(np, AREG);
  270.         } else {
  271.             frc_ral(0);
  272.             retreg(np, 0);
  273.         }
  274.     /* JMM
  275.       ? added XREF statement.  Note I use this regardless of whether
  276.        the function is defined in the module or not.  This is horrible
  277.        and may cause problems.    I will correct this when I can determine
  278.        whether the function is defined in the current module or is an
  279.        external reference. ?
  280.      */     externfuncref(np); /* see out.c */
  281.  
  282.         addcode(np, "\tjsr\t<A\n");
  283.         return OKAY;
  284.     case DOUBLE '+':
  285.         holdcon(np);
  286.         inherit(np);
  287.         addcode(np, "\tadd.S\t#K,A\n");
  288.         cc_hack(np);
  289.         return OKAY;
  290.     case DOUBLE '-':
  291.         holdcon(np);
  292.         inherit(np);
  293.         addcode(np, "\tsub.S\t#K,A\n");
  294.         cc_hack(np);
  295.         return OKAY;
  296.     case POSTINC:
  297.         if ((flags & NOVAL_OK) == 0) {
  298.             i = ralloc(0);
  299.             retreg(np, i);
  300.             addcode(np, "\tmove.S\t<A,A\n");
  301.         }
  302.         addcode(np, "\tadd.S\t#O,<A\n");
  303.         return OKAY;
  304.     case POSTDEC:
  305.         if ((flags & NOVAL_OK) == 0) {
  306.             i = ralloc(0);
  307.             retreg(np, i);
  308.             addcode(np, "\tmove.S\t<A,A\n");
  309.         }
  310.         addcode(np, "\tsub.S\t#O,<A\n");
  311.         return OKAY;
  312.     case CMPBR:
  313.         i = ralloc(0);
  314.         retreg(np, i);
  315.         addcode(np, "\tsN\tA\n\tand.w\t#1,A\n");
  316.         cc_hack(np);
  317.         return OKAY;
  318.     case '!':
  319.         if (flags & CC_OK) {
  320.             if (iscc(lp)) {
  321.                 i = cctok(lp);
  322.                 i = (i&1) ? i+1 : i-1;  /* reverse truth */
  323.             } else {
  324.                 i = B_EQ;
  325.                 addcode(np, "<Q");
  326.             }
  327.             np->g_token = i + BR_TOK;
  328.         } else {
  329.             if (istdreg(lp))
  330.                 i = lp->g_rno;
  331.             else
  332.                 i = ralloc(0);
  333.             retreg(np, i);
  334.             if (!iscc(lp))
  335.                 addcode(np, "<Q");
  336.             addcode(np, "\tseq\tA\n\tand.w\t#1,A\n");
  337.         }
  338.         return OKAY;
  339.     default:
  340.         printf("Weird u_eval %s ", np->n_name);
  341.         return FAIL;
  342.     }
  343. }
  344.  
  345. holdcon(np)
  346. NODEP np;
  347. {
  348.     np->g_bsize = np->g_offs;
  349. }
  350.  
  351. retreg(np, rno)
  352. NODEP np;
  353. {
  354.     np->g_token = REGVAR;
  355.     np->g_rno = rno;
  356. }
  357.  
  358. indir(np, rno)
  359. register NODEP np;
  360. {
  361.     np->g_token = OREG;
  362.     np->g_offs = 0;
  363.     np->g_rno = rno;
  364. }
  365.  
  366. inherit(np)
  367. register NODEP np;
  368. {
  369.     NODEP lp = np->n_left;
  370.  
  371.     np->g_token = lp->g_token;
  372.     np->g_offs = lp->g_offs;
  373.     np->g_rno = lp->g_rno;
  374.     np->g_flags |= CHILDNM | (lp->g_flags & IMMEDID);
  375. }
  376.  
  377. extern FILE *output;
  378.  
  379. cookmon(np, cookie)
  380. register NODEP np;
  381. {
  382.  
  383.     if (np == NULL) return FAIL;
  384.  
  385.     switch (cookie) {
  386.     case FORCC:
  387.         if (iscc(np)) {
  388.             outcode(np);
  389.             cctest = cctok(np);
  390.         } else {
  391.             if (np->g_token == ICON && isimmed(np)) {
  392.                 cctest = np->g_offs ? B_YES : B_NO;
  393.                 return OKAY;
  394.             }
  395.             outcode(np);
  396.             outsub("Q", np);
  397.             cctest = B_NE;
  398.         }
  399.         return OKAY;
  400.     case FORINIT:
  401.         if (anycode(np) == 0 && (np->g_flags & IMMEDID)) {
  402.             out_a(np, output);
  403.             return OKAY;
  404.         }
  405.         error("bad INIT expr");
  406.         return FAIL;
  407.     case IND0:
  408.         outcode(np);
  409.         if (np->g_token != REGVAR ||
  410.             np->g_rno != 0)
  411.             if (np->g_token == ICON && np->g_offs == 0 &&
  412.                 isimmed(np))
  413.                 outsub("\tclr.S\td0\n", np);
  414.             else
  415.                 outsub("\tmove.S\tA,d0\n", np);
  416.         return OKAY;
  417.     case RETSTRU:
  418.         outcode(np);
  419.         strret(np);
  420.     }
  421.     outcode(np);
  422.     return OKAY;
  423. }
  424.  
  425. anycode(np)
  426. register NODEP np;
  427. {
  428.     if (np->g_code)
  429.         return 1;
  430.     switch (np->g_type) {
  431.     case EV_NONE:
  432.         return 0;
  433.     case EV_LEFT:
  434.         return anycode(np->n_left);
  435.     case EV_RIGHT:
  436.         return anycode(np->n_right);
  437.     case EV_LR:
  438.     case EV_RL:
  439.         return anycode(np->n_left) || anycode(np->n_right);
  440.     }
  441. }
  442.  
  443. l_eval(np)
  444. register NODEP np;
  445. {
  446.     int l1;
  447.  
  448.     switch (np->g_token) {
  449.     case ID:
  450.         switch (np->g_sc) {
  451.         default:    /* EXTERN or HERE */
  452.             np->g_token = ONAME;
  453.             np->g_offs = 0;
  454.             if (np->n_name[0] != '%')
  455.                 nnmins(np, "_");
  456.             else    /* hack for inline name */
  457.                 strcpy(np->n_name, &np->n_name[1]);
  458.             return OKAY;        /* dont free n_nmx */
  459.         case K_STATIC:
  460.             sprintf(np->n_name, "L%d", (int)np->g_offs);
  461.             np->g_offs = 0;
  462.             np->g_token = ONAME;
  463.             break;
  464.         case K_AUTO:
  465.             np->g_rno = AREG+6;
  466.             np->g_token = OREG;
  467.             break;
  468.         case K_REGISTER:
  469.             np->g_token = REGVAR;
  470.             break;
  471.         }
  472.         if (np->n_nmx) {
  473.             freenode(np->n_nmx);
  474.             np->n_nmx = NULL;
  475.         }
  476.         return OKAY;
  477.     case ICON:
  478.         np->g_flags |= IMMEDID;
  479.         return OKAY;
  480.     case FCON:
  481.         np->g_flags |= IMMEDID;
  482.         return OKAY;
  483.     case SCON:
  484.         np->g_flags |= IMMEDID;
  485.         np->g_token = ONAME;
  486.         l1 = new_lbl();
  487.         save_scon(np, l1);
  488.         sprintf(np->n_name, "L%d", l1);
  489.         return OKAY;
  490.     case OREG:
  491.         return OKAY;
  492.     }
  493.     return FAIL;
  494. }
  495.  
  496. save_scon(np, lbl)
  497. NODEP np;
  498. {
  499.     NODEP tp, copyone();
  500.  
  501.     tp = copyone(np);
  502.     tp->g_offs = lbl;
  503.     if (np->n_nmx) {
  504.         freenode(np->n_nmx);
  505.         np->n_nmx = NULL;
  506.     }
  507.     putlist(&strsave, tp);
  508. }
  509.  
  510. utemp(np)
  511. NODEP np;
  512. {
  513.     NODEP lp = np->n_left;
  514.     int i;
  515.  
  516.     if (lp->g_token == REGVAR &&
  517.         istemp(lp->g_rno)) {
  518.         inherit(np);
  519.         return;
  520.     }
  521.     i = ralloc(0);
  522.     retreg(np, i);
  523.     addcode(np, "\tmove.S\t<A,A\n");
  524. }
  525.  
  526. freetmps(np)
  527. register NODEP np;
  528. {
  529.     if (np->g_r1 != -1)
  530.         rfree(np->g_r1);
  531.     if (np->g_r2 != -1)
  532.         rfree(np->g_r2);
  533. }
  534.  
  535. free1(np, cp)
  536. NODEP np, cp;
  537. {
  538.     int cr;
  539.  
  540.     if (cp->g_token != OREG && cp->g_token != REGVAR)
  541.         return;
  542.     cr = cp->g_rno;
  543.     if (np && cr == np->g_rno &&
  544.         (np->g_token == OREG || np->g_token == REGVAR))
  545.         return;
  546.     if (istemp(cr))
  547.         rfree(cr);
  548. }
  549.  
  550. istemp(rno)
  551. {
  552.     return (rno < DRV_START ||
  553.         (rno >= AREG && rno < ARV_START));
  554. }
  555.  
  556. rfree(rno)
  557. {
  558.     reserve &= ~(1<<rno);
  559. }
  560.  
  561. frc_ral(rno)
  562. {
  563.     int i;
  564.  
  565.     i = (1<<rno);
  566.     if (reserve & i)
  567.         error("rno reserved! ");
  568.     reserve |= i;
  569. }
  570.  
  571. tempr(np, type)
  572. NODEP np;
  573. {
  574.     int i;
  575.  
  576.     i = ralloc(type);
  577.     if (np->g_r1 == -1)
  578.         np->g_r1 = i;
  579.     else
  580.         np->g_r2 = i;
  581.     return i;
  582. }
  583.  
  584. ralloc(type)
  585. {
  586.     int starti, endi;
  587.     register int i;
  588.  
  589.     if (type == AREG) {
  590.         starti = AREG;
  591.         endi = ARV_START;
  592.     } else {
  593.         starti = 0;
  594.         endi = DRV_START;
  595.     }
  596.     for (i=starti; i<endi; i++)
  597.         if ((reserve & (1<<i)) == 0) {
  598.             reserve |= (1<<i);
  599.             return i;
  600.         }
  601.     error("Compiler failure - rallo");
  602.     return -1;
  603. }
  604.  
  605.  
  606. extern NODE *blktab;
  607. tmp_alloc(sz)
  608. {
  609.  
  610.     tmpused += sz;
  611.     return blktab->b_size + tmpused;
  612. }
  613.  
  614. /* fixes nodes with no code or aX is temp that are #d(aX) */
  615. imm_oreg(np)
  616. NODEP np;
  617. {
  618.     char *regnm(), buf[30];
  619.     int i;
  620.  
  621.     if (np->g_token != OREG)
  622.         return;
  623.     if ((np->g_flags & IMMEDID) == 0)
  624.         return;
  625.     np->g_flags &= ~IMMEDID;
  626.     if (np->g_offs == 0) {          /* #(a0) -> a0 */
  627.         np->g_token = REGVAR;
  628.         return;
  629.     }
  630.     if (istemp(np->g_rno)) {
  631.         holdcon(np);
  632.         addcode(np, "\tadd\t#K,A\n");
  633.         np->g_token = REGVAR;
  634.         return;
  635.     }
  636.     sprintf(buf, "\tlea\t%d(%s),A\n", (int)np->g_offs, regnm(np->g_rno));
  637.     addcode(np, buf);
  638.     i = ralloc(AREG);
  639.     retreg(np, i);
  640. }
  641.  
  642. castgen(tp)
  643. register NODEP tp;
  644. {
  645.     register NODEP np = tp->n_left;
  646.     int sz = tp->g_sz;
  647.     int i;
  648.  
  649.     if (np->g_token == ICON && isimmed(np)) {
  650.         if (tp->g_ty == ET_F) {
  651.             tp->g_token = FCON;
  652.             *(float *)&tp->g_offs = (float)np->g_offs;
  653.             tp->g_flags |= IMMEDID;
  654.         } else {
  655.             inherit(tp);
  656.             i_exp(tp, np->g_sz, np->g_ty);
  657.             squish(tp);
  658.         }
  659.     } else if (np->g_token == FCON && isimmed(np)) {
  660.         if (tp->g_ty != ET_F) {
  661.             tp->g_token = ICON;
  662.             tp->g_offs = (long)*(float *)&np->g_offs;
  663.             tp->g_flags |= IMMEDID;
  664.             squish(tp);
  665.         } else {
  666.             inherit(tp);
  667.         }
  668.     } else if (sz > np->g_sz) {
  669.         if (np->g_ty == ET_U) {
  670.             i = ralloc(0);
  671.             retreg(tp, i);
  672.             addcode(tp, "\tclr.S\tA\n\tmove.<S\t<A,A\n");
  673.         } else {
  674.             if (isdreg(np)) {
  675.                 inherit(tp);
  676.             } else {
  677.                 i = ralloc(0);
  678.                 retreg(tp, i);
  679.                 addcode(tp, "\tmove.<S\t<A,A\n");
  680.             }
  681.             if (sz == 4 && np->g_sz == 1)
  682.                 addcode(tp, "\text.w\tA\n\text.l\tA\n");
  683.             else
  684.                 addcode(tp, "\text.S\tA\n");
  685.         }
  686.         return;
  687.     }
  688.     else if (sz < np->g_sz) {
  689.         switch (np->g_token) {
  690.         case ONAME:
  691.         case OREG:
  692.             if (isimmed(np)) {
  693. smfudge:
  694.                 i = ralloc(0);
  695.                 retreg(tp, i);
  696.                 addcode(tp, "\tmove.<S\t<A,A\n");
  697.                 return;
  698.             }
  699.             inherit(tp);
  700.             tp->g_offs = np->g_offs + (np->g_sz - sz);
  701.             break;
  702.         case REGVAR:
  703.             if (sz == 1 && np->g_rno >= AREG)
  704.                 goto smfudge;
  705.             /* fall through */
  706.         default:
  707.             inherit(tp);
  708.         }
  709.     } else
  710.         inherit(tp);
  711. }
  712.  
  713. squish(np)
  714. NODEP np;
  715. {
  716.     int neg;
  717.  
  718.     neg = (np->g_ty == ET_S && np->g_offs < 0);
  719.  
  720.     switch (np->g_sz) {
  721.     case 1:
  722.         if (neg)
  723.             np->g_offs |= 0xffffff00L;
  724.         else
  725.             np->g_offs &= 0xff;
  726.         break;
  727.     case 2:
  728.         if (neg)
  729.             np->g_offs |= 0xffff0000L;
  730.         else
  731.             np->g_offs &= 0xffffL;
  732.         break;
  733.     }
  734. }
  735.  
  736. i_exp(np, osz, oty)
  737. NODEP np;
  738. {
  739.     long l;
  740.  
  741.     if (oty == ET_S && osz < np->g_sz) {
  742.         l = np->g_offs;
  743.         switch (osz) {
  744.         case 1:
  745.             l = (char) l;
  746.             break;
  747.         case 2:
  748.             l = (short) l;
  749.             break;
  750.         }
  751.         np->g_offs = l;
  752.     }
  753. }
  754. SHAR_EOF
  755. cat << \SHAR_EOF > gsub.c
  756. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  757.  *
  758.  * Permission is granted to anyone to use this software for any purpose
  759.  * on any computer system, and to redistribute it freely, with the
  760.  * following restrictions:
  761.  * 1) No charge may be made other than reasonable charges for reproduction.
  762.  * 2) Modified versions must be clearly marked as such.
  763.  * 3) The authors are not responsible for any harmful consequences
  764.  *    of using this software, even if they result from defects in it.
  765.  *
  766.  *    gsub.c
  767.  *
  768.  *    Various code generation subroutines
  769.  *    Includes generation of switches and
  770.  *    conversion of type lists to simple type,size.
  771.  */
  772.  
  773. #include <stdio.h>
  774. #include "param.h"
  775. #include "bstok.h"
  776. #include "tytok.h"
  777. #include "flags.h"
  778. #include "nodes.h"
  779. #include "gen.h"
  780.  
  781. #define isimmed(np)     ((np)->g_flags & IMMEDID)
  782. #define isareg(np)      ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
  783.  
  784. extern cctest;
  785.  
  786. extern xflags[];
  787. #define debug    xflags['s'-'a']
  788.  
  789. gen_brt(np, lbl)
  790. NODEP np;
  791. {
  792.     p2_expr(&np);
  793.     mustty(np, R_SCALAR);
  794.     br_sub(np, 0, lbl);
  795. }
  796.  
  797. gen_brf(np, lbl)
  798. NODEP np;
  799. {
  800.     p2_expr(&np);
  801.     mustty(np, R_SCALAR);
  802.     br_sub(np, 1, lbl);
  803. }
  804.  
  805. br_sub(np, rev, lbl)
  806. NODEP np;
  807. {
  808.     int i;
  809.  
  810.     switch (np->e_token) {
  811.         case DOUBLE '&':
  812.             br_split(np, lbl, rev);
  813.             return;
  814.         case DOUBLE '|':
  815.             br_split(np, lbl, 2+rev);
  816.             return;
  817.     }
  818.     genx(np, FORCC);
  819.     i = cctest;
  820.     if (i) {
  821.         if (rev)
  822.             /* reverse truth */
  823.             i = (i&1) ? i+1 : i-1;
  824.         out_b(i, lbl);
  825.     }
  826. }
  827.  
  828. br_split(np, lbl, n)
  829. NODEP np;
  830. {
  831.     int nlbl;
  832.  
  833.     if (n == 0 || n == 3)
  834.         nlbl = new_lbl();
  835.     else
  836.         nlbl = lbl;
  837.  
  838.     br_sub(np->n_left, n<2, nlbl);
  839.     br_sub(np->n_right, n&1, lbl);
  840.  
  841.     freeunit(np);
  842.  
  843.     if (nlbl != lbl)
  844.         def_lbl(nlbl);
  845. }
  846.  
  847. /* generate switch
  848.     np - list of nodes with value,label pairs (sorted)
  849.     dlbl - default label or -1
  850.  */
  851. #undef min
  852. #undef max
  853.  
  854. gen_switch(np, odlbl)
  855. NODEP np;
  856. {
  857.     int n,min,max;
  858.     int dlbl;
  859.     register NODEP p;
  860.  
  861.     if (debug) {
  862.         printf("gs %d ", odlbl);
  863.         printnode(np);
  864.     }
  865.  
  866.     /* if no default, make one! */
  867.     if (odlbl < 0)
  868.         dlbl = new_lbl();
  869.     else
  870.         dlbl = odlbl;
  871.  
  872.     n = 0;
  873.     for (p=np; p; p=p->n_next) {
  874.         if (n == 0)
  875.             min = max = p->c_casev;
  876.         else
  877.             max = p->c_casev;
  878.         n++;
  879.     }
  880.     if (n <= C_SIMPLE)
  881.         simple_sw(np,odlbl);
  882.     else if (n >= max/C_RATIO - min/C_RATIO)
  883.         table_sw(np,dlbl,min,max);
  884.     else {
  885.         half_sw(np,dlbl,max/2+min/2,n);
  886.         goto out;        /* free already done */
  887.     }
  888.     freenode(np);
  889. out:
  890.     if (odlbl < 0)
  891.         def_lbl(dlbl);
  892. }
  893.  
  894. /* simple if-else type switch
  895.     dlbl may be -1 -> fall through
  896.     does not free np
  897. */
  898. simple_sw(np, dlbl)
  899. register NODEP np;
  900. {
  901.     while (np) {
  902.         out_d0cmp(np->c_casev);
  903.         out_b(B_EQ, np->c_casel);
  904.         np = np->n_next;
  905.     }
  906.     if (dlbl >= 0)
  907.         out_br(dlbl);
  908. }
  909.  
  910. /* use table switch
  911.     dlbl is not -1
  912.     does not free np
  913. */
  914. table_sw(np, dlbl, min, max)
  915. NODEP np;
  916. {
  917.     out_d0cmp(min);
  918.     out_b(B_LT, dlbl);
  919.     out_d0cmp(max);
  920.     out_b(B_GT, dlbl);
  921.     if (min)
  922.         out_d0sub(min);
  923.  
  924.     out_tsw();
  925.  
  926.     while (np) {
  927.         while (min < np->c_casev) {
  928.             out_tlbl(dlbl);
  929.             min++;
  930.         }
  931.         out_tlbl(np->c_casel);
  932.         min++;
  933.         np = np->n_next;
  934.     }
  935. }
  936.  
  937. /* cut switch in half (by value)
  938.     dlbl is not -1
  939.     will free np
  940.  */
  941. half_sw(np, dlbl, cut, n)
  942. NODEP np;
  943. {
  944.     register NODEP p, last;
  945.     int nlo, nhi;
  946.     int l1;
  947.  
  948.     for (p=np; p->c_casev < cut; p = p->n_next)
  949.         last = p;
  950.     /* we KNOW both pieces are non-NULL ! */
  951.     last->n_next = NULL;
  952.     last = p;
  953.  
  954.     nlo = 0;
  955.     nhi = 0;
  956.     for (p=np; p; p=p->n_next)
  957.         nlo++;
  958.     nhi = n - nlo;
  959.  
  960.     if (nhi == 1) {         /* switch hi and low */
  961.         p = np;
  962.         np = last;
  963.         last = p;
  964.         nlo = 1;
  965.         nhi = n-1;
  966.     }
  967.     if (nlo == 1) {         /* also nhi == 1 */
  968.         out_d0cmp(np->c_casev);
  969.         out_b(B_EQ, np->c_casel);
  970.         freenode(np);
  971.         gen_switch(last, dlbl);
  972.         return;
  973.     }
  974.     l1 = new_lbl();
  975.     out_d0cmp(cut);
  976.     out_b(B_GE, l1);
  977.     gen_switch(np, dlbl);
  978.     def_lbl(l1);
  979.     gen_switch(last, dlbl);
  980. }
  981.  
  982. istempa(np)
  983. register NODEP np;
  984. {
  985.     if (np->g_token == OREG && istemp(np->g_rno))
  986.         return 1;
  987.     return 0;
  988. }
  989.  
  990. strasn(np)
  991. NODEP np;
  992. {
  993.     int r;
  994.     long size;
  995.     int chunk, l;
  996.     char buf[40];
  997.     int lisa, risa;
  998.  
  999.     if (np->g_ty != ET_A)
  1000.         return 0;
  1001.  
  1002.     size = np->g_bsize;
  1003.     if (size <= 4) {        /* pretend its scalar */
  1004.         np->g_sz = size;
  1005.         return 0;
  1006.     }
  1007.  
  1008.     lisa = istempa(np->n_left);
  1009.     risa = istempa(np->n_right);
  1010.  
  1011.     if (lisa)
  1012.         r = np->n_left->g_rno;
  1013.     else
  1014.         r = ralloc(AREG);       /* R0 */
  1015.     indir(np, r);
  1016.     np->g_offs = -size;
  1017.  
  1018.     if (size & 3)
  1019.         chunk = 2;
  1020.     else
  1021.         chunk = 4;
  1022.  
  1023.     if (risa)
  1024.         np->g_r1 = np->n_right->g_rno;
  1025.     else
  1026.         tempr(np, AREG);        /* R1 */
  1027.     tempr(np, 0);           /* R2 */
  1028.  
  1029.     if (!lisa || np->n_left->g_offs)
  1030.         addcode(np, "\tlea\t<A,R0\n");
  1031.     if (!risa || np->n_right->g_offs)
  1032.         addcode(np, "\tlea\t>A,R1\n");
  1033.     np->g_bsize = size/chunk - 1;
  1034.     addcode(np, "\tmove.w\t#K,R2\n");
  1035.     l = new_lbl();
  1036.     sprintf(buf, "'L%d:\tmove.%c\t(R1)+,(R0)+\n", l, chunk == 4 ?
  1037.         'l' : 'w');
  1038.     addcode(np, buf);
  1039.     sprintf(buf, "\tdbra\tR2,'L%d\n", l);
  1040.     addcode(np, buf);
  1041.  
  1042.     return 1;
  1043. }
  1044.  
  1045.  
  1046. extern funstrl;
  1047. strret(np)
  1048. NODEP np;
  1049. {
  1050.  
  1051.     strsub(np, funstrl);
  1052. }
  1053.  
  1054. strpush(np)
  1055. NODEP np;
  1056. {
  1057.     strsub(np, 0);
  1058. }
  1059.  
  1060. strsub(np, tolbl)
  1061. register NODEP np;
  1062. {
  1063.     long size;
  1064.     int chunk, l;
  1065.     char buf[40];
  1066.     char *frstr;
  1067.  
  1068.     size = np->g_bsize;
  1069.     if (size & 3)
  1070.         chunk = 2;
  1071.     else
  1072.         chunk = 4;
  1073.  
  1074.     tempr(np, 0);
  1075.  
  1076.     /* set up 'from' address */
  1077.     if (np->g_token == OREG && istemp(np->g_rno)) {
  1078.         frstr = "R0";
  1079.         if (np->g_offs)
  1080.             addcode(np, "\tlea\tA,R0\n");
  1081.     } else {
  1082.         frstr = "a1";
  1083.         addcode(np, "\tlea\tA,a1\n");
  1084.     }
  1085.  
  1086.     /* set up 'to' address */
  1087.     if (tolbl) {
  1088.         sprintf(buf, "\tmove.l\t#'L%d,a2\n", tolbl);
  1089.         addcode(np, buf);
  1090.     } else {
  1091.         sprintf(buf, "\tsub\t#%d,sp\n", (int)size);
  1092.         addcode(np, buf);
  1093.         addcode(np, "\tmove.l\tsp,a2\n");
  1094.     }
  1095.  
  1096.     /* generate copy loop */
  1097.     np->g_bsize = size/chunk - 1;
  1098.     addcode(np, "\tmove.w\t#K,R1\n");
  1099.     l = new_lbl();
  1100.     sprintf(buf, "'L%d:\tmove.%c\t(%s)+,(a2)+\n", l, chunk == 4 ?
  1101.         'l' : 'w', frstr);
  1102.     addcode(np, buf);
  1103.     sprintf(buf, "\tdbra\tR1,'L%d\n", l);
  1104.     addcode(np, buf);
  1105. }
  1106.  
  1107. specasn(np, flags)
  1108. NODEP np;
  1109. {
  1110.     NODEP lp = np->n_left, rp = np->n_right;
  1111.     int r;
  1112.  
  1113.     if (rp->g_token == ICON && isimmed(rp)) {
  1114.         rinherit(np);
  1115.  
  1116.         if (rp->g_offs == 0 && !isareg(rp))
  1117.             addcode(np, "\tclr.S\t<A\n");
  1118.         else
  1119.             addcode(np, "\tmove.S\t>A,<A\n");
  1120.         return 1;
  1121.     }
  1122.     if (rp->g_token == OREG && isimmed(rp)) {
  1123.         rp->g_flags &= ~IMMEDID;
  1124.         if (isareg(lp)) {
  1125.             inherit(np);
  1126.             addcode(np, "\tlea\t>A,A\n");
  1127.         } else {
  1128.             r = ralloc(AREG);
  1129.             retreg(np, r);
  1130.             addcode(np, "\tlea\t>A,A\n");
  1131.             addcode(np, "\tmove.l\tA,<A\n");
  1132.         }
  1133.         return 1;
  1134.     }
  1135.     return 0;
  1136. }
  1137.  
  1138. untype(np)
  1139. register NODEP np;
  1140. {
  1141.     if (np == NULL || np->n_tptr == NULL) {
  1142.         printf("? NULL untype ");
  1143.         return;
  1144.     }
  1145.  
  1146.     switch (np->e_type) {
  1147.     case E_BIN:
  1148.         untype(np->n_right);
  1149.         /* fall through */
  1150.     case E_UNARY:
  1151.         if (np->e_token == '.' && np->e_fldw) {
  1152.             np->g_fldw = np->e_fldw;
  1153.             np->g_fldo = np->e_fldo;
  1154.         } else
  1155.             np->g_fldw = 0;
  1156.  
  1157.         untype(np->n_left);
  1158.     }
  1159.  
  1160.     get_tyinf(np);
  1161.  
  1162.     if ((np->n_flags & N_COPYT) == 0)
  1163.         freenode(np->n_tptr);
  1164.     np->n_tptr = NULL;        /* is g_code */
  1165.     np->g_betw = NULL;
  1166. }
  1167.  
  1168. static char bty[] = {
  1169.     ET_U, ET_U, ET_S, ET_S, ET_U, ET_S, ET_S, ET_F, ET_F, 0
  1170. };
  1171.  
  1172. static char bsz[] = {
  1173.     SIZE_C, SIZE_L, SIZE_L, SIZE_S, SIZE_U,
  1174.     SIZE_I, SIZE_C, SIZE_F, SIZE_D, 0
  1175. };
  1176.  
  1177. get_tyinf(np)
  1178. register NODEP np;
  1179. {
  1180.     NODEP tp = np->n_tptr;
  1181.     int n;
  1182.     long offs;
  1183.  
  1184.     offs = np->e_offs;
  1185.  
  1186.     /* inherit name,token,left,right,nmx from common
  1187.         and token, flags, type, sc from enode */
  1188.  
  1189.     switch (tp->t_token) {
  1190.     case K_STRUCT:
  1191.     case K_UNION:
  1192.         np->g_bsize = tp->t_size;
  1193.         np->g_ty = ET_A;
  1194.         np->g_sz = 0;
  1195.         break;
  1196.     case '(':
  1197.         break;
  1198.     case STAR:
  1199.         np->g_ty = ET_U;
  1200.         np->g_sz = SIZE_P;
  1201.         break;
  1202.     default:
  1203.         n = tp->t_token-FIRST_BAS;
  1204.         np->g_ty = bty[n];
  1205.         np->g_sz = bsz[n];
  1206.     }
  1207.     np->g_offs = offs;    /* different place */
  1208. }
  1209.  
  1210. addcode(np, s)
  1211. register NODEP np;
  1212. char *s;
  1213. {
  1214.     NODEP tp;
  1215.     int i, c;
  1216.  
  1217.     while (np->g_code)
  1218.         np = np->g_code;
  1219.     tp = allocnode();
  1220.     np->g_code = tp;
  1221.     np->n_flags &= ~N_COPYT;
  1222.     i = strlen(s);
  1223.     if (i < NMXSIZE) {      /* fits in one */
  1224.         strcpy(tp->n_name, s);
  1225.         return;
  1226.     }
  1227.  
  1228.     /* need to split it */
  1229.     i = NMXSIZE-1;
  1230.     c = s[i-1];
  1231.     if (c == '<' || c == '>' || (c>='A' && c<='Z')) /* special */
  1232.         i--;
  1233.     strncpy(tp->n_name, s, i);
  1234.     tp->n_name[i] = 0;
  1235.     addcode(tp, &s[i]);
  1236. }
  1237. SHAR_EOF
  1238. cat << \SHAR_EOF > gunk.c
  1239. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  1240.  *
  1241.  * Permission is granted to anyone to use this software for any purpose
  1242.  * on any computer system, and to redistribute it freely, with the
  1243.  * following restrictions:
  1244.  * 1) No charge may be made other than reasonable charges for reproduction.
  1245.  * 2) Modified versions must be clearly marked as such.
  1246.  * 3) The authors are not responsible for any harmful consequences
  1247.  *    of using this software, even if they result from defects in it.
  1248.  *
  1249.  *    gunk.c
  1250.  *
  1251.  *    Transformations on expression trees
  1252.  *    Most of this stuff is because we cant handle
  1253.  *    floats, long mul/div, or fields directly.
  1254.  */
  1255.  
  1256. #include <stdio.h>
  1257. #include "param.h"
  1258. #include "bstok.h"
  1259. #include "tytok.h"
  1260. #include "flags.h"
  1261. #include "nodes.h"
  1262. #include "gen.h"
  1263.  
  1264. NODEP copyone();
  1265.  
  1266. #define gwiden(x)    ((x)==1 ? 2 : (x))
  1267. #define isfield(np)    ((np)->g_token == '.' && (np)->g_fldw)
  1268.  
  1269. NODEP npar1, npar2, npar3;
  1270. char *spar1, *spar2, *spar3;
  1271. int ipar1, ipar2, ipar3;
  1272.  
  1273. struct rule {
  1274.     int (*match)();        /* test for transformation needed */
  1275.     int (*rewri)();        /* rewrite function */
  1276. };
  1277.  
  1278. int m_unfold(), unfold(), m_cast(), cast(), m_inline(), inline();
  1279. int m_hardas(), hardas(), m_fcmp(), fcmp(), m_md_shf(), md_shf();
  1280. int m_eident(), eident(), m_incdec(), incdec(), m_fldas(), fldas();
  1281.  
  1282. struct rule gunktbl[] = {
  1283.     {m_unfold, unfold},
  1284.     {m_cast, cast},
  1285.     {m_md_shf, md_shf},
  1286.     {m_eident, eident},
  1287.     {m_incdec, incdec},
  1288.     {m_hardas, hardas},
  1289.     {m_inline, inline}, /* must cast before inline */
  1290.     {m_fcmp, fcmp},
  1291.     {m_fldas, fldas},
  1292.     {0}
  1293. };
  1294.  
  1295. int anygunk;
  1296.  
  1297. gunk(np)
  1298. NODEP np;
  1299. {
  1300.     do {
  1301.         anygunk = 0;
  1302.         gunks(np);
  1303.     } while (anygunk);
  1304. }
  1305.  
  1306. gunks(np)
  1307. register NODEP np;
  1308. {
  1309.     switch (np->g_type) {
  1310.     case E_BIN:
  1311.         gunks(np->n_right);
  1312.     case E_UNARY:
  1313.         gunks(np->n_left);
  1314.     }
  1315.     gunk1(np);
  1316. }
  1317.  
  1318. gunk1(np)
  1319. NODEP np;
  1320. {
  1321.     register struct rule *p;
  1322.  
  1323.     for (p=gunktbl; p->match; p++)
  1324.         if ((*p->match)(np)) {
  1325.             anygunk++;
  1326.             (*p->rewri)(np);
  1327.             return;
  1328.         }
  1329. }
  1330.  
  1331. /*
  1332.  *    Change pointer arithmetic to equivalent trees
  1333.  *        (main thing is to mult or div by object size)
  1334.  */
  1335. m_unfold(np)
  1336. NODEP np;
  1337. {
  1338.     switch (np->g_token) {
  1339.     case PTRADD:
  1340.         ipar1 = '+';
  1341.         return 1;
  1342.     case PTRSUB:
  1343.         ipar1 = '-';
  1344.         return 1;
  1345.     case PTRDIFF:
  1346.         ipar1 = 0;
  1347.         return 1;
  1348.     case ASSIGN PTRADD:
  1349.         ipar1 = ASSIGN '+';
  1350.         return 1;
  1351.     case ASSIGN PTRSUB:
  1352.         ipar1 = ASSIGN '-';
  1353.         return 1;
  1354.     }
  1355.     return 0;
  1356. }
  1357.  
  1358. unfold(np)
  1359. NODEP np;
  1360. {
  1361.     if (ipar1) {
  1362.         ins_mul(np, np->g_offs);
  1363.         np->g_token = ipar1;
  1364.     } else {
  1365.         ins_div(np, np->g_offs);
  1366.     }
  1367. }
  1368.  
  1369. NODEP
  1370. newgcon(kon, ty, sz)
  1371. long kon;
  1372. {
  1373.     register NODEP kp;
  1374.  
  1375.     kp = allocnode();
  1376.     kp->g_token = ICON;
  1377.     sprintf(kp->n_name, "%ld", kon);
  1378.     kp->g_offs = kon;
  1379.     kp->g_type = E_LEAF;
  1380.     kp->g_ty = ty;
  1381.     kp->g_sz = sz;
  1382.     return kp;
  1383. }
  1384.  
  1385. ins_mul(np, kon)
  1386. NODEP np;
  1387. long kon;
  1388. {
  1389.     NODEP rp = np->n_right;
  1390.     register NODEP mp, kp;
  1391.  
  1392.     if (kon == 1)
  1393.         return;
  1394.     if (rp->g_token == ICON) {
  1395.         rp->g_offs *= kon;
  1396.         rp->g_sz = gwiden(rp->g_sz);
  1397.         return;
  1398.     }
  1399.  
  1400.     mp = allocnode();
  1401.     mp->g_token = '*';
  1402.     sprintf(mp->n_name, "p*");
  1403.     mp->g_type = E_BIN;
  1404.     mp->g_ty = rp->g_ty;
  1405.     mp->g_sz = gwiden(rp->g_sz);
  1406.  
  1407.     kp = newgcon(kon, mp->g_ty, mp->g_sz);
  1408.  
  1409.     mp->n_right = kp;
  1410.     mp->n_left = np->n_right;
  1411.     np->n_right = mp;
  1412. }
  1413.  
  1414. ins_div(np, kon)
  1415. register NODEP np;
  1416. long kon;
  1417. {
  1418.     register NODEP tp, kp;
  1419.  
  1420.     kp = newgcon(kon, np->g_ty, np->g_sz);
  1421.  
  1422.     tp = copyone(np);
  1423.     tp->g_token = '-';
  1424.     tp->n_left = np->n_left;
  1425.     tp->n_right = np->n_right;
  1426.     tp->g_sz = SIZE_P;
  1427.     tp->g_ty = ET_U;
  1428.  
  1429.     np->n_left = tp;
  1430.     np->n_right = kp;
  1431.     np->g_type = E_BIN;
  1432.     np->g_token = '/';
  1433.     sprintf(np->n_name, "p/");
  1434. }
  1435.  
  1436. #define CAST_LN    1
  1437. #define CAST_RN 2
  1438. #define CAST_LLONG    3
  1439.  
  1440. /*
  1441.  *    Insert needed (implied) casts
  1442.  */
  1443. m_cast(np)
  1444. NODEP np;
  1445. {
  1446.     NODEP lp = np->n_left;
  1447.  
  1448.     switch (np->g_type) {
  1449.     case E_LEAF:
  1450.         return 0;
  1451.     case E_BIN:
  1452.         return bm_cast(np);
  1453.     }
  1454.     /* must be unary */
  1455.     switch (np->g_token) {
  1456.     case UNARY '-':
  1457.     case '~':
  1458.         return castup(lp, np, CAST_LN);
  1459.     case TCONV:
  1460.         return fcastlong(np);
  1461.     }
  1462.     return 0;
  1463. }
  1464.  
  1465. bm_cast(np)
  1466. register NODEP np;
  1467. {
  1468.     NODEP lp = np->n_left, rp = np->n_right;
  1469.  
  1470.     if (isassign(np->g_token)) {
  1471.         if (castup(rp, lp, CAST_RN))
  1472.             return 1;
  1473.         if (castmagic(rp, lp, CAST_RN, np->g_token - (ASSIGN 0)))
  1474.             return 1;
  1475.         return 0;
  1476.     }
  1477.  
  1478.     switch (np->g_token) {
  1479.     case '=':
  1480.         return castany(rp, lp, CAST_RN);
  1481.  
  1482.     case '<':
  1483.     case '>':
  1484.     case DOUBLE '=':
  1485.     case NOTEQ:
  1486.     case LTEQ:
  1487.     case GTEQ:
  1488.         if (castup(lp, rp, CAST_LN))
  1489.             return 1;
  1490.         return castup(rp, lp, CAST_RN);
  1491.  
  1492.     case '(':
  1493.     case ',':
  1494.     case '?':
  1495.     case DOUBLE '&':
  1496.     case DOUBLE '|':
  1497.         return 0;
  1498.  
  1499.     case DOUBLE '<':
  1500.     case DOUBLE '>':
  1501.         if (castup(lp, np, CAST_LN))
  1502.             return 1;
  1503.         return castany(rp, np, CAST_RN);
  1504.  
  1505.     default:
  1506.         if (castup(lp, np, CAST_LN))
  1507.             return 1;
  1508.         return castup(rp, np, CAST_RN);
  1509.     }
  1510.     return 0;
  1511. }
  1512.  
  1513. fcastlong(np)
  1514. NODEP np;
  1515. {
  1516.     NODEP lp = np->n_left;
  1517.  
  1518.     if (red_con(lp))
  1519.         return 0;
  1520.     if (np->g_ty == ET_F && lp->g_ty != ET_F && lp->g_sz != SIZE_L) {
  1521.         ipar1 = CAST_LLONG;
  1522.         return 1;
  1523.     }
  1524.     if (lp->g_ty == ET_F && np->g_ty != ET_F && np->g_sz != SIZE_L) {
  1525.         ipar1 = CAST_LLONG;
  1526.         return 1;
  1527.     }
  1528.     return 0;
  1529. }
  1530.  
  1531. castup(lowp, hip, par)
  1532. NODEP lowp, hip;
  1533. {
  1534.     if (stronger(hip, lowp)) {
  1535.         ipar1 = par;
  1536.         npar1 = hip;
  1537.         return 1;
  1538.     }
  1539.     return 0;
  1540. }
  1541.  
  1542. castmagic(p1, p2, par, tok)
  1543. NODEP p1, p2;
  1544. {
  1545.     if (xstronger(p1,p2) && magicop(tok)) {
  1546.         ipar1 = par;
  1547.         npar1 = p2;
  1548.         return 1;
  1549.     }
  1550.     return 0;
  1551. }
  1552.  
  1553. castany(p1, p2, par)
  1554. NODEP p1, p2;
  1555. {
  1556.     if (p1->g_sz != p2->g_sz ||
  1557.         ((p1->g_ty == ET_F) != (p2->g_ty == ET_F))) {
  1558.         ipar1 = par;
  1559.         npar1 = p2;
  1560.         return 1;
  1561.     }
  1562.     return 0;
  1563. }
  1564.  
  1565. cast(np)
  1566. NODEP np;
  1567. {
  1568.     switch (ipar1) {
  1569.     case CAST_LN:
  1570.         castsub(npar1->g_ty, npar1->g_sz, &np->n_left, np->n_left);
  1571.         break;
  1572.     case CAST_RN:
  1573.         castsub(npar1->g_ty, npar1->g_sz, &np->n_right, np->n_right);
  1574.         break;
  1575.     case CAST_LLONG:
  1576.         castsub(ET_S, SIZE_L, &np->n_left, np->n_left);
  1577.         break;
  1578.     }
  1579. }
  1580.  
  1581. castsub(ty, sz, npp, np)
  1582. NODEP *npp, np;
  1583. {
  1584.     register NODEP tp;
  1585.  
  1586.     /* ICON cast optimization */
  1587.     if (np->g_token == ICON &&
  1588.         np->g_ty == ty &&
  1589.         np->g_sz < sz) {
  1590.         np->g_sz = sz;
  1591.         return;
  1592.     }
  1593.  
  1594.     tp = allocnode();
  1595.     tp->g_token = TCONV;
  1596.     strcpy(tp->n_name, "cast up");
  1597.     tp->n_left = np;
  1598.     *npp = tp;
  1599.     tp->g_sz = sz;
  1600.     tp->g_ty = ty;
  1601.     tp->g_type = E_UNARY;
  1602. }
  1603.  
  1604. /*
  1605.  *    Change stuff computer cant do to calls to inline functions
  1606.  *    (in this case, all floats and long *%/)
  1607.  */
  1608. m_inline(np)
  1609. NODEP np;
  1610. {
  1611.     int isfloat, isuns;
  1612.  
  1613.     if (np->g_type == E_LEAF)
  1614.         return 0;
  1615.  
  1616.     isfloat = (np->g_ty == ET_F);
  1617.     isuns = (np->g_ty == ET_U);
  1618.  
  1619.     if (np->g_type == E_UNARY) {
  1620.         switch (np->g_token) {
  1621.         case UNARY '-':
  1622.             if (!isfloat) return 0;
  1623.             spar1 = "%fpneg";
  1624.             return 1;
  1625.         case TCONV:
  1626.             if ((np->n_left->g_ty == ET_F) == isfloat)
  1627.                 return 0;
  1628.             if (red_con(np->n_left))
  1629.                 return 0;
  1630.             spar1 = isfloat ? "fpltof" : "fpftol";
  1631.             return 1;
  1632.         }
  1633.         return 0;
  1634.     }
  1635.  
  1636.     if (np->g_sz != 4)    /* longs or floats only */
  1637.         return 0;
  1638.  
  1639.     switch (np->g_token) {
  1640.     case '*':
  1641.         spar1 = isfloat ? "%fpmul" : (isuns ? "%lmulu" : "%lmul");
  1642.         return 1;
  1643.     case '/':
  1644.         spar1 = isfloat ? "%fpdiv" : (isuns ? "%ldivu" : "%ldiv");
  1645.         return 1;
  1646.     case '+':
  1647.         if (!isfloat) return 0;
  1648.         spar1 = "%fpadd";
  1649.         return 1;
  1650.     case '-':
  1651.         if (!isfloat) return 0;
  1652.         spar1 = "%fpsub";
  1653.         return 1;
  1654.     case '%':
  1655.         spar1 = isuns ? "%lremu" : "%lrem";
  1656.         return 1;
  1657.     }
  1658.     return 0;
  1659. }
  1660.  
  1661. inline(np)
  1662. NODEP np;
  1663. {
  1664.     register NODEP nmp, cmap;
  1665.     int isunary;
  1666.  
  1667.     isunary = (np->g_type == E_UNARY);
  1668.  
  1669.     if (isunary) {
  1670.         np->n_right = np->n_left;
  1671.         np->g_type = E_BIN;
  1672.     } else {
  1673.         cmap = copyone(np);
  1674.         cmap->n_left = np->n_left;
  1675.         cmap->n_right = np->n_right;
  1676.         np->n_right = cmap;
  1677.  
  1678.         cmap->g_token = ',';
  1679.         cmap->g_offs = 2;
  1680.         strcpy(cmap->n_name, ",inl");
  1681.     }
  1682.  
  1683.     nmp = allocnode();
  1684.     np->n_left = nmp;
  1685.  
  1686.     np->g_token = '(';
  1687.     strcpy(np->n_name, "inline");
  1688.  
  1689.     nmp->g_token = ID;
  1690.     strcpy(nmp->n_name, spar1);
  1691. }
  1692.  
  1693. /*
  1694.  *    Transform hard ++,-- to equivalent trees
  1695.  *    (for us, floats or fields)
  1696.  */
  1697. m_incdec(np)
  1698. NODEP np;
  1699. {
  1700.     if (np->g_type != E_UNARY)
  1701.         return 0;
  1702.     if (np->g_ty != ET_F && !isfield(np->n_left))
  1703.         return 0;
  1704.  
  1705.     ipar2 = 0;
  1706.     switch (np->g_token) {
  1707.     case DOUBLE '+':
  1708.         ipar1 = ASSIGN '+';
  1709.         spar1 = "+=";
  1710.         break;
  1711.     case DOUBLE '-':
  1712.         ipar1 = ASSIGN '-';
  1713.         spar1 = "-=";
  1714.         break;
  1715.     case POSTINC:
  1716.         ipar1 = DOUBLE '+';
  1717.         spar1 = "++";
  1718.         ipar2 = '-';
  1719.         spar2 = "-";
  1720.         break;
  1721.     case POSTDEC:
  1722.         ipar1 = DOUBLE '-';
  1723.         spar1 = "--";
  1724.         ipar2 = '+';
  1725.         spar2 = "+";
  1726.         break;
  1727.     default:
  1728.         return 0;
  1729.     }
  1730.     return 1;
  1731. }
  1732.  
  1733. incdec(np)
  1734. register NODEP np;
  1735. {
  1736.     NODEP t1;
  1737.     NODEP onep;
  1738.  
  1739.     onep = newgcon(1L, ET_S, SIZE_I);
  1740.  
  1741.     if (ipar2 == 0) {        /* easy case, ++X becomes X+=1 */
  1742.         np->g_token = ipar1;
  1743.         np->g_type = E_BIN;
  1744.         np->n_right = onep;
  1745.         strcpy(np->n_name, spar1);
  1746.         return;
  1747.     }
  1748.  
  1749.     /* hard case, X++ becomes (++X - 1) */
  1750.     t1 = copyone(np);
  1751.     t1->n_left = np->n_left;
  1752.     np->n_left = t1;
  1753.     np->n_right = onep;
  1754.     np->g_type = E_BIN;
  1755.     np->g_token = ipar2;
  1756.     strcpy(np->n_name, spar2);
  1757.  
  1758.     t1->g_token = ipar1;
  1759.     strcpy(t1->n_name, spar1);
  1760. }
  1761.  
  1762. /*
  1763.  *    Transform hard op= trees to equivalent '=' trees
  1764.  *    (in this case, all floats, long or char *%/, fields)
  1765.  */
  1766. m_hardas(np)
  1767. NODEP np;
  1768. {
  1769.     int op;
  1770.  
  1771.     if (np->g_type != E_BIN)
  1772.         return 0;
  1773.     op = np->g_token;
  1774.     if (isassign(op))
  1775.         op -= ASSIGN 0;
  1776.     else
  1777.         return 0;
  1778.     if (xstronger(np->n_right, np->n_left) &&
  1779.         magicop(op) == 0)
  1780.         return 1;
  1781.     if (np->g_ty == ET_F || isfield(np->n_left))
  1782.         return 1;
  1783.     if (np->g_sz == 4 || np->g_sz == 1)
  1784.         switch (op) {
  1785.         case '*':
  1786.         case '/':
  1787.         case '%':
  1788.             return 1;
  1789.         }
  1790.     return 0;
  1791. }
  1792.  
  1793. hardas(np)
  1794. NODEP np;
  1795. {
  1796.     NODEP opp, newl;
  1797.     NODEP copynode();
  1798.  
  1799.     if (m_vhard(np)) {
  1800.         vhard(np);
  1801.         return;
  1802.     }
  1803.  
  1804.     opp = copyone(np);
  1805.     newl = copynode(np->n_left);
  1806.     opp->n_right = np->n_right;
  1807.     np->n_right = opp;
  1808.     opp->n_left = newl;
  1809.  
  1810.     np->g_token = '=';
  1811.     strcpy(np->n_name, "unfold");
  1812.  
  1813.     opp->g_token -= (ASSIGN 0);
  1814.     bmaxty(opp);
  1815. }
  1816.  
  1817. /*
  1818.  *    Check for lhs of op= that have side effects or are complex
  1819.  */
  1820. m_vhard(np)
  1821. NODEP np;
  1822. {
  1823.     NODEP lp = np->n_left;
  1824.  
  1825.     while (lp->g_token == '.')
  1826.         lp = lp->n_left;
  1827.     if (lp->g_token != STAR)
  1828.         return 0;
  1829.     return isvhard(lp->n_left);
  1830. }
  1831.  
  1832. isvhard(np)
  1833. NODEP np;
  1834. {
  1835.     NODEP rp;
  1836.  
  1837. descend:
  1838.     switch (np->g_type) {
  1839.     case E_LEAF:
  1840.         return 0;
  1841.     case E_UNARY:
  1842.         switch (np->g_token) {
  1843.         case '(':
  1844.         case DOUBLE '+':
  1845.         case DOUBLE '-':
  1846.         case POSTINC:
  1847.         case POSTDEC:
  1848.             return 1;
  1849.         default:
  1850.             np = np->n_left;
  1851.             goto descend;
  1852.         }
  1853.     case E_BIN:
  1854.         switch (np->g_token) {
  1855.         case '+':
  1856.         case '-':
  1857.             rp = np->n_right;
  1858.             if (rp->g_token == ICON && np->g_ty != ET_F) {
  1859.                 np = np->n_left;
  1860.                 goto descend;
  1861.             }
  1862.             /* fall through */
  1863.         default:
  1864.             return 1;
  1865.         }
  1866.     }
  1867. }
  1868.  
  1869. vhard(np)
  1870. NODEP np;
  1871. {
  1872.     NODEP starp;
  1873.     NODEP atree, btree;
  1874.     NODEP t1, t2;
  1875.     register NODEP opp;
  1876.     NODEP tmp_var();
  1877.  
  1878.     starp = np->n_left;
  1879.     while (starp->g_token == '.')
  1880.         starp = starp->n_left;
  1881.     atree = starp->n_left;
  1882.     btree = np->n_right;
  1883.     t1 = tmp_var(ET_U, SIZE_P);
  1884.     t2 = copyone(t1);
  1885.     starp->n_left = t2;
  1886.  
  1887.     opp = copyone(t1);
  1888.     opp->g_type = E_BIN;
  1889.     opp->g_token = '=';
  1890.     strcpy(opp->n_name, "=");
  1891.     opp->n_right = atree;
  1892.     opp->n_left = t1;
  1893.  
  1894.     comma_r(np, opp);
  1895. }
  1896.  
  1897. comma_r(topp, lp)
  1898. NODEP topp, lp;
  1899. {
  1900.     register NODEP newp;
  1901.  
  1902.     newp = copyone(topp);
  1903.     topp->g_token = ',';
  1904.     strcpy(topp->n_name, ",");
  1905.     newp->n_left = topp->n_left;
  1906.     newp->n_right = topp->n_right;
  1907.     topp->n_left = lp;
  1908.     topp->n_right = newp;
  1909. }
  1910.  
  1911. NODEP
  1912. tmp_var(ty, sz)
  1913. {
  1914.     register NODEP t1;
  1915.  
  1916.     t1 = allocnode();
  1917.     t1->g_token = OREG;
  1918.     t1->g_type = E_LEAF;
  1919.     t1->g_rno = AREG+6;
  1920.     t1->g_ty = ty;
  1921.     t1->g_sz = sz;
  1922.     t1->g_offs = - tmp_alloc(sz);
  1923.     strcpy(t1->n_name, "tmp_v");
  1924.     return t1;
  1925. }
  1926.  
  1927. /* X op= Y where Y's type is stronger than X's
  1928.     either unfold it or (default)
  1929.     cast Y to weaker type (+ or -)
  1930. */
  1931.  
  1932. magicop(op)
  1933. {
  1934.     switch (op) {
  1935.     case '+':
  1936.     case '-':
  1937.     case DOUBLE '<':
  1938.     case DOUBLE '>':
  1939.     case '&':
  1940.     case '|':
  1941.     case '^':
  1942.         return 1;
  1943.     }
  1944.     return 0;
  1945. }
  1946.  
  1947. stronger(xp, yp)
  1948. NODEP xp, yp;
  1949. {
  1950.     if (xp->g_sz > yp->g_sz || 
  1951.         (xp->g_sz == yp->g_sz && xp->g_ty > yp->g_ty))
  1952.         return 1;
  1953.     return 0;
  1954. }
  1955.  
  1956. /* stronger with ET_S and ET_U considered equal */
  1957. xstronger(xp, yp)
  1958. NODEP xp, yp;
  1959. {
  1960.     if (xp->g_sz > yp->g_sz ||
  1961.         (xp->g_ty == ET_F && yp->g_ty != ET_F))
  1962.         return 1;
  1963.     return 0;
  1964. }
  1965.  
  1966. /* give np the type of the stronger child */
  1967. bmaxty(np)
  1968. NODEP np;
  1969. {
  1970.     NODEP lp = np->n_left, rp = np->n_right;
  1971.  
  1972.     if (stronger(lp, rp))
  1973.         rp = lp;
  1974.     np->g_ty = rp->g_ty;
  1975.     np->g_sz = gwiden(rp->g_sz);
  1976. }
  1977.  
  1978. /*
  1979.  *    Change floating compares to inline call 
  1980.  */
  1981. m_fcmp(np)
  1982. NODEP np;
  1983. {
  1984.         /* already made L and R same with casts */
  1985.     if (np->g_type != E_BIN || np->n_left->g_ty != ET_F)
  1986.         return 0;
  1987.     switch (np->g_token) {
  1988.     case '<':
  1989.         spar2 = "lt";
  1990.         return 1;
  1991.     case '>':
  1992.         spar2 = "gt";
  1993.         return 1;
  1994.     case DOUBLE '=':
  1995.         spar2 = "eq";
  1996.         return 1;
  1997.     case NOTEQ:
  1998.         spar2 = "ne";
  1999.         return 1;
  2000.     case GTEQ:
  2001.         spar2 = "ge";
  2002.         return 1;
  2003.     case LTEQ:
  2004.         spar2 = "le";
  2005.         return 1;
  2006.     }
  2007.     return 0;
  2008. }
  2009.  
  2010. fcmp(np)
  2011. register NODEP np;
  2012. {
  2013.     register NODEP tp;
  2014.  
  2015.     spar1 = "%fpcmp";
  2016.     inline(np);
  2017.  
  2018.     tp = copyone(np);
  2019.     tp->n_left = np->n_left;
  2020.     tp->n_right = np->n_right;
  2021.     np->n_left = tp;
  2022.  
  2023.     np->n_right = NULL;
  2024.     np->g_type = E_UNARY;
  2025.     np->g_token = CMPBR;
  2026.     sprintf(np->n_name, spar2);
  2027. }
  2028.  
  2029. /*
  2030.  *    Remove useless binary operations with identity constant
  2031.  */
  2032. m_eident(np)
  2033. NODEP np;
  2034. {
  2035.     NODEP rp = np->n_right;
  2036.     long l;
  2037.     int i, op;
  2038.  
  2039.     if (np->g_type != E_BIN)
  2040.         return 0;
  2041.     if (np->g_ty == ET_F)
  2042.         return 0;
  2043.     while (rp->g_token == TCONV && rp->g_ty != ET_F)
  2044.         rp = rp->n_left;
  2045.     if (rp->g_token != ICON)
  2046.         return 0;
  2047.     l = rp->g_offs;
  2048.     if (l < 0 || l > 1)
  2049.         return 0;
  2050.  
  2051.     op = np->g_token;
  2052.     if (isassign(op))
  2053.         op -= ASSIGN 0;
  2054.     switch (op) {
  2055.     case '+':
  2056.     case '-':
  2057.     case DOUBLE '<':
  2058.     case DOUBLE '>':
  2059.     case '|':
  2060.     case '^':
  2061.         i = 0;    break;
  2062.     case '*':
  2063.     case '/':
  2064.         i = 1;  break;
  2065.     default:
  2066.         return 0;
  2067.     }
  2068.     if (l != i)
  2069.         return 0;
  2070.     return 1;    
  2071. }
  2072.  
  2073. eident(np)
  2074. NODEP np;
  2075. {
  2076.     NODEP lp = np->n_left, rp = np->n_right;
  2077.  
  2078.     freenode(rp);
  2079.     
  2080.     lcpy(np, lp, sizeof(NODE)/4);
  2081.  
  2082.     freeunit(lp);
  2083. }
  2084.  
  2085. #define MAXLOOK    8
  2086.  
  2087. /*
  2088.  *    Change certain mult or div to equivalent shift
  2089.  */
  2090. m_md_shf(np)
  2091. NODEP np;
  2092. {
  2093.     NODEP rp = np->n_right;
  2094.     long l;
  2095.     register i, j;
  2096.  
  2097.     if (np->g_type != E_BIN)
  2098.         return 0;
  2099.     if (np->g_ty == ET_F)
  2100.         return 0;
  2101.     while (rp->g_token == TCONV && rp->g_ty != ET_F)
  2102.         rp = rp->n_left;
  2103.     if (rp->g_token != ICON)
  2104.         return 0;
  2105.  
  2106.     switch (np->g_token) {
  2107.     case '*':
  2108.         ipar1 = DOUBLE '<';  break;
  2109.     case '/':
  2110.         ipar1 = DOUBLE '>';  break;
  2111.     case ASSIGN '*':
  2112.         ipar1 = ASSIGN DOUBLE '<';  break;
  2113.     case ASSIGN '/':
  2114.         ipar1 = ASSIGN DOUBLE '>';  break;
  2115.     default:
  2116.         return 0;
  2117.     }
  2118.  
  2119.     l = rp->g_offs;
  2120.     if (l < 2 || l > (1<<MAXLOOK))
  2121.         return 0;
  2122.     i = l;
  2123.     for (j=1; j<=MAXLOOK; j++)
  2124.         if (i == 1<<j) {
  2125.             ipar2 = j;
  2126.             return 1;
  2127.         }
  2128.     return 0;
  2129. }
  2130.  
  2131. md_shf(np)
  2132. NODEP np;
  2133. {
  2134.     NODEP rp = np->n_right;
  2135.  
  2136.     np->g_token = ipar1;
  2137.     while (rp->g_token == TCONV)
  2138.         rp = rp->n_left;
  2139.     rp->g_offs = ipar2;
  2140. }
  2141.  
  2142. m_fldas(np)
  2143. NODEP np;
  2144. {
  2145.     if (np->g_type != E_BIN)
  2146.         return 0;
  2147.     if (np->g_token == '=' && isfield(np->n_left))
  2148.         return 1;
  2149. }
  2150.  
  2151. fldas(np)
  2152. register NODEP np;
  2153. {
  2154.     NODEP lp = np->n_left;
  2155.  
  2156.     np->g_fldw = lp->g_fldw;
  2157.     np->g_fldo = lp->g_fldo;
  2158.     np->g_token = FIELDAS;
  2159.  
  2160.     lp->g_fldw = 0;
  2161. }
  2162.  
  2163. red_con(np)
  2164. register NODEP np;
  2165. {
  2166.     while (np->g_token == TCONV)
  2167.         np = np->n_left;
  2168.     if (np->g_token == ICON || np->g_token == FCON)
  2169.         return 1;
  2170.     return 0;
  2171. }
  2172. SHAR_EOF
  2173. cat << \SHAR_EOF > main.c
  2174. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2175.  *
  2176.  * Permission is granted to anyone to use this software for any purpose
  2177.  * on any computer system, and to redistribute it freely, with the
  2178.  * following restrictions:
  2179.  * 1) No charge may be made other than reasonable charges for reproduction.
  2180.  * 2) Modified versions must be clearly marked as such.
  2181.  * 3) The authors are not responsible for any harmful consequences
  2182.  *    of using this software, even if they result from defects in it.
  2183.  *
  2184.  *    main.c
  2185.  *
  2186.  *    Main routine, error handling, keyword lookup.
  2187.  *
  2188.  *
  2189.  *   Revised: Dec 1988    Joe Montgomery
  2190.  *
  2191.  *   Revised main.c to use Amiga File System Naming Conventions
  2192.  *    Added ?,C,F switches. ? help
  2193.  *                  C force data,bss into Chip memory
  2194.  *                  F force data,bss into Fast memory
  2195.  *    To be added -o switch to specify assembly output
  2196.  *
  2197.  *     other modules:
  2198.  *   Revised out.c to use MOTOROLA assembly directives in order
  2199.  *    to be compatible with C.Gibbs a68k assembler & blink
  2200.  *    Added END statement
  2201.  *    Changed .comm label,size to label DC.x 0
  2202.  *   Revised d2.c so that externs are declared as XREF -----
  2203.  *   Revised g2.c & gen.c to declare all called functions XREF
  2204.  *     (will need to change this to declare only external functions)
  2205.  *
  2206.  *
  2207.  *   All changes labeled JMM
  2208.  */
  2209.  
  2210. #include <stdio.h>
  2211. #include "param.h"
  2212. #include "nodes.h"
  2213. #include "tok.h"
  2214.  
  2215. extern short usechipmemory,usefastmemory;
  2216. int lineno;
  2217. int nmerrors;
  2218. int oflags[26];
  2219. int xflags[26];
  2220. int pflag = 0;            /* enable profiling */
  2221. static int anydebug;
  2222. #define debug oflags['z'-'a']
  2223.  
  2224.  
  2225. FILE *input;
  2226. FILE *output;
  2227. #if CC68
  2228. FILE *fopenb();
  2229. #define fopen fopenb
  2230. #endif
  2231. char *inname;
  2232.  
  2233. #if NEEDBUF
  2234. char my_ibuf[BUFSIZ];
  2235. #endif
  2236.  
  2237. NODEP cur;
  2238.  
  2239. /* JMM changed defines to be compatible with AMIGA */
  2240. static    char *defines[] = {
  2241.     "MC68000",
  2242.     "mc68000",
  2243.     "SOZOBON",
  2244.     "MCH_AMIGA",
  2245.     "AmigaDOS",
  2246.     NULL
  2247. };
  2248.  
  2249. static    char    Version[] =
  2250. "zc: Amiga Version 1.01  Copyright (c) 1988 by Sozobon, Limited.\n";
  2251.  
  2252. static char Version2[] =
  2253. "    modified by J.Montgomery. Now generates Motorola compatible \n";
  2254. static char Version3[] =
  2255. "   assembly code.\n";
  2256. extern char *outfilename,*errorfile;
  2257.  
  2258.  
  2259. main(argc, argv)
  2260. char **argv;
  2261. {
  2262.     char    *p, *getenv();
  2263.     int shownames;
  2264.     int i;
  2265.  
  2266. /* JMM added switches to force data,bss into chip or fast memory */
  2267.     usefastmemory = 0;
  2268.     usechipmemory = 0;  /* don't force data into either chip or fast*/
  2269.     outfilename = (char *) NULL;
  2270.  
  2271. /* JMM force hcc to always print out version */
  2272.     printf(Version);
  2273.     if (sizeof(NODE) & 3) {
  2274.         printf("sizeof NODE not mult of 4\n");
  2275.         exit(1);
  2276.     }
  2277.  
  2278.     /*
  2279.      * Define the "built-in" macros
  2280.      */
  2281.     for (i=0; defines[i] != NULL; i++)
  2282.         optdef(defines[i]);
  2283.  
  2284.     /*
  2285.      * Parse the INCLUDE environment variable, if present.
  2286.      */
  2287.     if ((p = getenv("INCLUDE")) != NULL){
  2288.         if( doincl(p) == 1 )exit(0);
  2289.     }
  2290.     shownames = 0;
  2291.     if (isatty(0)) {
  2292.         write(1, "\33v", 2);
  2293.         setbuf(stdout, NULL);
  2294.     }
  2295. /* put author here */
  2296.     while (argc-- > 1) {
  2297.         argv++;
  2298.         if(argv[0][0] == '?') {
  2299.             doopt(&argv[0][0]);
  2300.             exit(1);
  2301.         }
  2302.         if(argv[0][0] == '-')
  2303.               doopt(&argv[0][1]);
  2304. #if CC68
  2305.         else if (argv[0][0] == '+') {
  2306.             upstr(&argv[0][1]);
  2307.             doopt(&argv[0][1]);
  2308.         }
  2309. #endif
  2310.         else {
  2311.             if (argc > 1 || shownames) {
  2312.                 shownames++;
  2313.                 printf("%s:\n", argv[0]);
  2314.             }
  2315.             if (input != NULL)
  2316.                 fclose(input);
  2317.             input = fopen(argv[0], ROPEN);
  2318.             if (input == NULL) {
  2319.                 printf("Cant open %s\n", argv[0]);
  2320.                 exit(1);
  2321.             }
  2322. #if NEEDBUF
  2323.             setbuf(input, my_ibuf);
  2324. #endif
  2325.             inname = argv[0];
  2326.             dofile();
  2327.         }
  2328.     }
  2329.     if (input == NULL) {
  2330.         input = stdin;
  2331.         output = stdout;
  2332.         inname = "<STDIN>";
  2333.         dofile();
  2334.     }
  2335.     exit(0);
  2336. }
  2337.  
  2338. doincl(s)
  2339. char    *s;
  2340. {
  2341.     char    *malloc(), *strcpy();
  2342.     char    buf[256];
  2343.     char    dir[128];
  2344.     register char    *p;
  2345.  
  2346.  
  2347.     strcpy(buf, s);
  2348.     /*
  2349.      * Convert ',' and ';' to nulls
  2350.      */
  2351.     for (p=buf; *p != '\0' ;p++)
  2352.         if (*p == ',' || *p == ';')
  2353.             *p = '\0';
  2354.     p[1] = '\0';                    /* double null terminated */
  2355.  
  2356.     /*
  2357.      * Grab each directory, make sure it ends with a slash,
  2358.      * and add it to the directory list.
  2359.      */
  2360.     for (p=buf; *p != '\0' ;p++) {
  2361.         strcpy(dir, p);
  2362.       /* JMM use Amiga file naming conventions */
  2363.         if (dir[strlen(dir)-1] != '/' && dir[strlen(dir)-1] != ':')
  2364.             strcat(dir, "/");
  2365.  
  2366.         optincl( strcpy(malloc((unsigned) (strlen(dir) + 1)), dir) );
  2367.  
  2368.         while (*p != '\0')
  2369.             p++;
  2370.     }
  2371. }
  2372.  
  2373.  
  2374. extern int nodesmade, nodesavail;
  2375. extern NODEP deflist[], symtab[], tagtab;
  2376. extern NODEP strsave;
  2377. extern int level;
  2378. dofile()
  2379. {
  2380.     char *scopy();
  2381.     int i;
  2382.  
  2383.     out_start(inname);
  2384.     inname = scopy(inname);
  2385.     lineno = 1;
  2386.     nmerrors = 0;
  2387.     advnode();
  2388.  
  2389.     level = 0;
  2390.     program();
  2391.     dumpstrs(strsave);
  2392.  
  2393.     out_end();
  2394.     if (cur && cur->e_token == EOFTOK)
  2395.         freenode(cur);
  2396.     sfree(inname);
  2397.     for (i=0; i<NHASH; i++) {
  2398.         if (debug>1 && deflist[i]) {
  2399.             printf("defines[%d]", i);
  2400.             printlist(deflist[i]);
  2401.         }
  2402.         freenode(deflist[i]);
  2403.         deflist[i] = NULL;
  2404.         if (debug && symtab[i]) {
  2405.             printf("gsyms[%d]", i);
  2406.             printlist(symtab[i]);
  2407.         }
  2408.         freenode(symtab[i]);
  2409.         symtab[i] = NULL;
  2410.     }
  2411.     if (debug) {
  2412.         printf("structs");
  2413.         printlist(tagtab);
  2414.     }
  2415.     freenode(tagtab);
  2416.     tagtab = NULL;
  2417.     freenode(strsave);
  2418.     strsave = NULL;
  2419.     if (nmerrors) {
  2420.         printf("%d errors\n", nmerrors);
  2421.         exit(1);
  2422.     }
  2423.     if (nodesmade != nodesavail) {
  2424.         printf("lost %d nodes!!!\n", nodesmade-nodesavail);
  2425.         exit(1);
  2426.     }
  2427. /*
  2428.     printf("Space = %ldK\n", ((long)nodesavail*sizeof(NODE))/1024);
  2429. */
  2430. }
  2431.  
  2432. dooutfile(s)
  2433. char    *s;
  2434. {
  2435.      char    *malloc(), *strcpy();
  2436.  
  2437.      outfilename = strcpy(malloc((unsigned)(strlen(s) + 1)), s );
  2438. }
  2439.  
  2440. doerrorfile(s)
  2441. char *s;
  2442. {
  2443.      char  *malloc(),*strcpy();
  2444.  
  2445.      errorfile = strcpy(malloc((unsigned)(strlen(s) + 1)), s);
  2446. }
  2447.  
  2448. doopt(s)
  2449. char *s;
  2450. {
  2451.     register char c;
  2452.  
  2453.     while ((c = *s++)) {
  2454. #ifdef    DEBUG
  2455.         if (c >= 'a' && c <='z') {
  2456.             oflags[c-'a']++;
  2457.             anydebug++;
  2458.         } else
  2459. #endif
  2460.         if ( (c >= 'A' && c <= 'Z') || c == '?') {
  2461.             switch (c) {
  2462.             case 'D':
  2463.                 optdef(s);
  2464.                 return;
  2465.             case 'U':
  2466.                 optundef(s);
  2467.                 return;
  2468.             case 'I':
  2469.                 doincl(s);
  2470.                 return;
  2471.             case 'P':
  2472.                 pflag = 1;
  2473.                 continue;
  2474.             case 'V':
  2475.                 printf("%s %s",Version2,Version3);
  2476.                 continue;
  2477. /* JMM added ?,C,F,O,E    switches */
  2478.             case 'E': /* specify error file */
  2479.                 doerrorfile(s);
  2480.                 return(1);
  2481.             case 'O':
  2482.                 dooutfile(s);
  2483.                 return(1);
  2484.             case 'C':
  2485.                 if(usefastmemory){
  2486.                    printf(" Can't use both Chip & Fast memory\n");
  2487.                    return(1);
  2488.                 }
  2489.                 usechipmemory = 1;
  2490.                 continue;
  2491.              case 'F':
  2492.                 if(usechipmemory){
  2493.                    printf(" Can't use both Chip & Fast memory\n");
  2494.                    return(1);
  2495.                 }
  2496.                 usefastmemory = 1;
  2497.                 continue;
  2498.             case '?':
  2499.                 printf("%s %s",Version2,Version3);
  2500.                 printf("    The Correct Syntax is \n");
  2501.                 printf("zc [FLAGS] SOURCEFILE \n");
  2502.                 printf("    The valid compiler flags are : \n");
  2503.                 printf("\n  -Dxxxx   Define xxxx\n  -Uxxxx   Undefine xxxx\n");
  2504.                 printf("  -Ixxxx   Include Directory = xxxx\n  -P   profiler\n");
  2505.                 printf("  -Oxxxx   outputfile name = xxxx\n");
  2506.                 printf("  -V   display compiler version\n  -?   Help\n");
  2507.                 printf("  -C   force Data,Bss into Chip memory \n");
  2508.                 printf("  -F   force Data,Bss into Fast memory \n");
  2509.                 return(1);
  2510.                 continue;
  2511.             }
  2512. #ifdef    DEBUG
  2513.             xflags[c-'A']++;
  2514.             anydebug++;
  2515. #endif
  2516.         }
  2517.     }
  2518. return(0);
  2519. }
  2520.  
  2521. errors(s,t)
  2522. char *s, *t;
  2523. {
  2524.     optnl();
  2525.     printf("error in %s on line %d: %s %s\n", inname, lineno, s,t);
  2526.     nmerrors++;
  2527. }
  2528.  
  2529. errorn(s,np)
  2530. char *s;
  2531. NODE *np;
  2532. {
  2533.     optnl();
  2534.     printf("error in %s on line %d: %s ", inname, lineno, s);
  2535.     put_nnm(np);
  2536.     putchar('\n');
  2537.     nmerrors++;
  2538. }
  2539.  
  2540. error(s)
  2541. char *s;
  2542. {
  2543.     optnl();
  2544.     printf("error in %s on line %d: %s\n", inname, lineno, s);
  2545.     nmerrors++;
  2546. }
  2547.  
  2548. warns(s,t)
  2549. char *s, *t;
  2550. {
  2551.     optnl();
  2552.     printf("warning in %s on line %d: %s %s\n", inname, lineno, s,t);
  2553. }
  2554.  
  2555. warnn(s,np)
  2556. char *s;
  2557. NODE *np;
  2558. {
  2559.     optnl();
  2560.     printf("warning in %s on line %d: %s ", inname, lineno, s);
  2561.     put_nnm(np);
  2562.     putchar('\n');
  2563. }
  2564.  
  2565. warn(s)
  2566. char *s;
  2567. {
  2568.     optnl();
  2569.     printf("warning in %s on line %d: %s\n", inname, lineno, s);
  2570. }
  2571.  
  2572. fatals(s,t)
  2573. char *s, *t;
  2574. {
  2575.     optnl();
  2576.     printf("fatal error in %s on line %d: %s %s\n", inname, lineno, s,t);
  2577.     exit(1);
  2578. }
  2579.  
  2580. fataln(s,np)
  2581. char *s;
  2582. NODE *np;
  2583. {
  2584.     optnl();
  2585.     printf("fatal error in %s on line %d: %s ", inname, lineno, s);
  2586.     put_nnm(np);
  2587.     putchar('\n');
  2588.     exit(1);
  2589. }
  2590.  
  2591. fatal(s)
  2592. char *s;
  2593. {
  2594.     optnl();
  2595.     printf("fatal error in %s on line %d: %s\n", inname, lineno, s);
  2596.     exit(1);
  2597. }
  2598.  
  2599. static
  2600. optnl()
  2601. {
  2602.     if (anydebug)
  2603.         putchar('\n');
  2604. }
  2605.  
  2606. struct kwtbl {
  2607.     char *name;
  2608.     int    kwval;
  2609.     int    kflags;
  2610. } kwtab[] = {
  2611.     /* must be sorted */
  2612.     {"asm", K_ASM},
  2613.     {"auto", K_AUTO},
  2614.     {"break", K_BREAK},
  2615.     {"case", K_CASE},
  2616.     {"char", K_CHAR},
  2617.     {"continue", K_CONTINUE},
  2618.     {"default", K_DEFAULT},
  2619.     {"do", K_DO},
  2620.     {"double", K_DOUBLE},
  2621.     {"else", K_ELSE},
  2622.     {"enum", K_ENUM},
  2623.     {"extern", K_EXTERN},
  2624.     {"float", K_FLOAT},
  2625.     {"for", K_FOR},
  2626.     {"goto", K_GOTO},
  2627.     {"if", K_IF},
  2628.     {"int", K_INT},
  2629.     {"long", K_LONG},
  2630.     {"register", K_REGISTER},
  2631.     {"return", K_RETURN},
  2632.     {"short", K_SHORT},
  2633.     {"sizeof", K_SIZEOF},
  2634.     {"static", K_STATIC},
  2635.     {"struct", K_STRUCT},
  2636.     {"switch", K_SWITCH},
  2637.     {"typedef", K_TYPEDEF},
  2638.     {"union", K_UNION},
  2639.     {"unsigned", K_UNSIGNED},
  2640.     {"void", K_VOID},
  2641.     {"while", K_WHILE},
  2642.  
  2643.     {0,0}
  2644. };
  2645.  
  2646. #define FIRST_C 'a'
  2647. #define LAST_C    'z'
  2648. struct kwtbl *kwstart[LAST_C-FIRST_C+1];
  2649.  
  2650. kw_init()
  2651. {
  2652.     register struct kwtbl *p;
  2653.     register c;
  2654.  
  2655.     for (p=kwtab; p->name; p++) {
  2656.         c = p->name[0];
  2657.         if (kwstart[c-FIRST_C] == 0)
  2658.             kwstart[c-FIRST_C] = p;
  2659.     }
  2660. }
  2661.  
  2662. kw_tok(tp)
  2663. NODE *tp;
  2664. {
  2665.     register struct kwtbl *kp;
  2666.     register char *nm;
  2667.     register i;
  2668.     static first = 0;
  2669.  
  2670.     nm = tp->n_name;
  2671.     if (first == 0) {
  2672.         kw_init();
  2673.         first = 1;
  2674.     }
  2675.     i = nm[0];
  2676.     if (i < FIRST_C || i > LAST_C)
  2677.         return;
  2678.     kp = kwstart[i-FIRST_C];
  2679.     if (kp)
  2680.     for (; kp->name; kp++) {
  2681.         i = strcmp(nm, kp->name);
  2682.         if (i == 0) {
  2683.             tp->e_token = kp->kwval;
  2684.             tp->e_flags = kp->kflags;
  2685.             return;
  2686.         } else if (i < 0)
  2687.             return;
  2688.     }
  2689. }
  2690.  
  2691. #if CC68
  2692. /* fix args since stupid lib makes all lower case */
  2693. upstr(s)
  2694. char *s;
  2695. {
  2696.     while (*s) {
  2697.         if (*s >= 'a' && *s <= 'z')
  2698.             *s += 'A'-'a';
  2699.         s++;
  2700.     }
  2701. }
  2702. downstr(s)
  2703. char *s;
  2704. {
  2705.     while (*s) {
  2706.         if (*s >= 'A' && *s <= 'Z')
  2707.             *s -= 'A'-'a';
  2708.         s++;
  2709.     }
  2710. }
  2711. #endif
  2712. SHAR_EOF
  2713. cat << \SHAR_EOF > md.c
  2714. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2715.  *
  2716.  * Permission is granted to anyone to use this software for any purpose
  2717.  * on any computer system, and to redistribute it freely, with the
  2718.  * following restrictions:
  2719.  * 1) No charge may be made other than reasonable charges for reproduction.
  2720.  * 2) Modified versions must be clearly marked as such.
  2721.  * 3) The authors are not responsible for any harmful consequences
  2722.  *    of using this software, even if they result from defects in it.
  2723.  *
  2724.  *    md.c
  2725.  *
  2726.  *    Machine dependant parts of first pass (parse)
  2727.  *    Also type checking subroutines.
  2728.  */
  2729.  
  2730. #include <stdio.h>
  2731. #include "param.h"
  2732. #include "tok.h"
  2733. #include "nodes.h"
  2734. #include "cookie.h"
  2735.  
  2736. NODEP bas_type();
  2737.  
  2738. int adjtab[] = {
  2739.     K_INT,        /* none */
  2740.     K_SHORT,    /* short */
  2741.     K_LONG,     /* long */
  2742.     0,        /* short long */
  2743.     K_UNSIGNED,    /* unsigned */
  2744.     K_UNSIGNED,    /* unsigned short */
  2745.     T_ULONG,    /* unsigned long */
  2746.     0,        /* unsigned short long */
  2747. };
  2748.  
  2749. adj_type(old, adj)
  2750. {
  2751.     int rv;
  2752.  
  2753.     switch (old) {
  2754.     case K_CHAR:
  2755.         if (adj & SAW_UNS)
  2756.             return T_UCHAR;
  2757.         break;
  2758.     case K_INT:
  2759.         rv = adjtab[adj];
  2760.         if (rv == 0) {
  2761.             error("bad type spec");
  2762.             return K_INT;
  2763.         }
  2764.         return rv;
  2765.     case K_FLOAT:
  2766.         if (adj & SAW_LONG)
  2767.             return K_DOUBLE;
  2768.         break;
  2769.     }
  2770.     return old;
  2771. }
  2772.  
  2773. /* given ICON value, and flags SEE_L,SEE_U
  2774.     determine final type */
  2775. icon_ty(tp)
  2776. NODE *tp;
  2777. {
  2778.     int flags;
  2779.     long val;
  2780.     int islong, isuns;
  2781.  
  2782.     flags = tp->e_flags;
  2783.     val = tp->e_ival;
  2784.  
  2785.     islong = (flags & SEE_L);
  2786.     isuns = (flags & SEE_U);
  2787.  
  2788.     if (islong && isuns)
  2789.         return T_ULONG;
  2790.     if (islong || islongv(val))
  2791.         return K_LONG;
  2792.     if (isuns)
  2793.         return K_UNSIGNED;
  2794.     return isintv((int)val) ? K_INT : K_CHAR;
  2795. }
  2796.  
  2797. isintv(i)
  2798. {
  2799.     if (i > 0x7f || i < -0x80)
  2800.         return 1;
  2801.     return 0;
  2802. }
  2803.  
  2804. islongv(l)
  2805. long l;
  2806. {
  2807. #ifndef NOLONGS
  2808.     if (l > MAXUNS || l < MININT)
  2809.         return 1;
  2810. #endif
  2811.     return 0;
  2812. }
  2813.  
  2814. mkint(l)
  2815. long l;
  2816. {
  2817.     return l;
  2818. }
  2819.  
  2820. lc_reg(rp, xp)
  2821. int *rp;
  2822. NODE *xp;
  2823. {
  2824.     switch (xp->n_tptr->t_token) {
  2825.     case STAR:
  2826.         return al_areg(rp,xp);
  2827.     case K_CHAR:
  2828.     case T_UCHAR:
  2829.     case T_ULONG:
  2830.     case K_INT:
  2831.     case K_UNSIGNED:
  2832.     case K_LONG:
  2833.         return al_dreg(rp,xp);
  2834.     default:
  2835.         return 0;
  2836.     }
  2837. }
  2838.  
  2839. al_areg(rp,xp)
  2840. int *rp;
  2841. NODEP xp;
  2842. {
  2843.     register rmask, n;
  2844.  
  2845.     rmask = *rp;
  2846.     for (n=ARV_START; n<=ARV_END; n++)
  2847.         if ((rmask & (1<<n)) == 0) {
  2848.             xp->e_rno = n;
  2849.             *rp |= (1<<n);
  2850.             return 1;
  2851.         }
  2852.     return 0;
  2853. }
  2854.  
  2855. al_dreg(rp,xp)
  2856. int *rp;
  2857. NODEP xp;
  2858. {
  2859.     register rmask, n;
  2860.  
  2861.     rmask = *rp;
  2862.     for (n=DRV_START; n<=DRV_END; n++)
  2863.         if ((rmask & (1<<n)) == 0) {
  2864.             xp->e_rno = n;
  2865.             *rp |= (1<<n);
  2866.             return 1;
  2867.         }
  2868.     return 0;
  2869. }
  2870.  
  2871. long
  2872. arg_size(sz,np)
  2873. long sz;
  2874. NODEP np;
  2875. {
  2876.     np->e_offs = 0;
  2877.  
  2878.     switch (np->n_tptr->t_token) {
  2879.     case '[':
  2880.         printf("GAK! array arg ");
  2881.         return SIZE_P;
  2882.     case K_CHAR:
  2883.     case T_UCHAR:
  2884.         np->e_offs = SIZE_I - SIZE_C;
  2885.         return SIZE_I;
  2886. #if SIZE_I != SIZE_S
  2887.     case K_SHORT:
  2888.         np->e_offs = SIZE_I - SIZE_S;
  2889.         return SIZE_I;
  2890. #endif
  2891.     default:
  2892.         return sz;
  2893.     }
  2894. }
  2895.  
  2896. mustlval(np)
  2897. NODEP np;
  2898. {
  2899.     switch (np->e_token) {
  2900.     case ID:
  2901.     case STAR:
  2902.     case '.':
  2903.         break;
  2904.     default:
  2905.         errorn("not lvalue", np);
  2906.         return 1;
  2907.     }
  2908.     return 0;
  2909. }
  2910.  
  2911. mustty(np, flags)
  2912. NODEP np;
  2913. {
  2914.     switch (np->n_tptr->t_token) {
  2915.     case STAR:
  2916.         if (flags & R_POINTER)
  2917.             return 0;
  2918.         error("pointer not allowed");
  2919.         return 1;
  2920.     case K_STRUCT:
  2921.     case K_UNION:
  2922.         if (flags & R_STRUCT)
  2923.             return 0;
  2924.         error("struct/union not allowed");
  2925.         return 1;
  2926.     case K_CHAR:
  2927.     case K_SHORT:
  2928.     case K_INT:
  2929.     case K_UNSIGNED:
  2930.     case K_LONG:
  2931.     case T_UCHAR:
  2932.     case T_ULONG:
  2933.         if (flags & R_INTEGRAL)
  2934.             return 0;
  2935.         error("integral not allowed");
  2936.         return 1;
  2937.     case K_FLOAT:
  2938.     case K_DOUBLE:
  2939.         if (flags & R_FLOATING)
  2940.             return 0;
  2941.         error("floating not allowed");
  2942.         return 1;
  2943.     default:
  2944.         error("bad type");
  2945.         return 1;
  2946.     }
  2947.     return 0;
  2948. }
  2949.  
  2950. NODEP
  2951. functy(np)
  2952. NODEP np;
  2953. {
  2954.     int lt;
  2955.  
  2956.     lt = np->n_tptr->t_token;
  2957.     if (lt != K_VOID)
  2958.         mustty(np, R_ASSN);
  2959.     switch (lt) {
  2960.     case STAR:
  2961.     case K_STRUCT:
  2962.     case K_UNION:
  2963.         return np->n_tptr;
  2964.     }
  2965.     lt = widen(lt);
  2966.     return bas_type(lt);
  2967. }
  2968.  
  2969. NODEP
  2970. normalty(lp, rp)
  2971. NODEP lp, rp;
  2972. {
  2973.     /* already checked types are R_ARITH */
  2974.     /* rp may be NULL */
  2975.     int lt, rt, rett;
  2976.  
  2977.     lt = lp->n_tptr->t_token;
  2978.     if (rp)
  2979.         rt = rp->n_tptr->t_token;
  2980.     else
  2981.         rt = K_INT;
  2982.     rett = maxt(widen(lt), widen(rt));
  2983.     return bas_type(rett);
  2984. }
  2985.  
  2986. asn_chk(ltp, rp)
  2987. NODEP ltp, rp;
  2988. {
  2989.  
  2990.     switch (ltp->t_token) {
  2991.     case K_STRUCT:
  2992.     case K_UNION:
  2993.         if (same_type(ltp, rp->n_tptr) == 0)
  2994.             error("bad struct assign");
  2995.         return;
  2996.     case STAR:
  2997.         if (mayzero(rp))
  2998.             return;
  2999.         if (mustty(rp, R_POINTER))
  3000.             return;
  3001.         if (same_type(ltp->n_tptr, rp->n_tptr->n_tptr)
  3002.             == 0)
  3003.             warn("pointer types mismatch");
  3004.         return;
  3005.     default:
  3006.         if (mustty(rp, R_ARITH))
  3007.             return;
  3008.     }
  3009. }
  3010.  
  3011. chkcmp(np)
  3012. NODEP np;
  3013. {
  3014.     /* already checked types are R_SCALAR */
  3015.     int lt, rt;
  3016.     NODEP lp = np->n_left, rp = np->n_right;
  3017.  
  3018.     lt = lp->n_tptr->t_token;
  3019.     lt = (lt == STAR);
  3020.     rt = rp->n_tptr->t_token;
  3021.     rt = (rt == STAR);
  3022.     if (lt && rt) {         /* ptr cmp ptr */
  3023.         if (same_type(lp->n_tptr, rp->n_tptr) == 0) {
  3024.             warn("cmp of diff ptrs");
  3025.         }
  3026.     } else if (lt) {        /* ptr cmp intg */
  3027.         mustzero(rp);
  3028.     } else if (rt) {        /* intg +-[ ptr */
  3029.         mustzero(lp);
  3030.     } /* else both ARITH */
  3031. }
  3032.  
  3033. NODEP
  3034. colonty(np)
  3035. NODEP np;
  3036. {
  3037.     /* already checked types are R_SCALAR */
  3038.     int lt, rt;
  3039.     NODEP lp = np->n_left, rp = np->n_right;
  3040.  
  3041.     lt = lp->n_tptr->t_token;
  3042.     lt = (lt == STAR);
  3043.     rt = rp->n_tptr->t_token;
  3044.     rt = (rt == STAR);
  3045.     if (lt && rt) {         /* ptr : ptr */
  3046.         warn(": diff ptrs");
  3047.         return lp->n_tptr;
  3048.     } else if (lt) {        /* ptr : intg */
  3049.         mustzero(rp);
  3050.         return lp->n_tptr;
  3051.     } else if (rt) {
  3052.         mustzero(lp);
  3053.         return rp->n_tptr;
  3054.     } else
  3055.         return normalty(lp, rp);
  3056. }
  3057.  
  3058. NODEP
  3059. addty(np)
  3060. NODEP np;
  3061. {
  3062.     /* already checked types are R_SCALAR */
  3063.     /* op is '+' or '-' or '+=' or '-=' or '[' */
  3064.     int oop = np->e_token;
  3065.     int op;
  3066.     int lt, rt;
  3067.     NODEP lp = np->n_left, rp = np->n_right;
  3068.  
  3069.     op = oop;
  3070.     if (isassign(op))
  3071.         op -= ASSIGN 0;
  3072.     lt = lp->n_tptr->t_token;
  3073.     lt = (lt == STAR);
  3074.     rt = rp->n_tptr->t_token;
  3075.     rt = (rt == STAR);
  3076.     if (lt && rt) {         /* ptr - ptr */
  3077.         if (oop != '-' || same_type(lp->n_tptr, rp->n_tptr) == 0) {
  3078.             error("bad +/-");
  3079.             return lp->n_tptr;
  3080.         }
  3081.         np->e_token = PTRDIFF;
  3082.         np->e_offs = lp->n_tptr->n_tptr->t_size;
  3083.         return bas_type(K_INT);
  3084.     } else if (lt) {        /* ptr +-[ intg */
  3085. pandi:
  3086.         mustty(rp, R_INTEGRAL);
  3087.         np->e_offs = lp->n_tptr->n_tptr->t_size;
  3088.         if (op == '+')
  3089.             np->e_token += PTRADD-'+';
  3090.         else if (op == '-')
  3091.             np->e_token += PTRSUB-'-';
  3092.         return lp->n_tptr;
  3093.     } else if (rt) {        /* intg +-[ ptr */
  3094.         if (isassign(oop) || op == '-') {
  3095.             error("illegal int op ptr");
  3096.             return bas_type(K_INT);
  3097.         }
  3098.         /* switch sides so intg is on right */
  3099.         np->n_left = rp;
  3100.         np->n_right = lp;
  3101.         lp = rp;
  3102.         rp = np->n_right;
  3103.         goto pandi;
  3104.     } else {        /* intg +- intg */
  3105.         return normalty(lp, rp);
  3106.     }
  3107. }
  3108.  
  3109. mustzero(np)
  3110. NODEP np;
  3111. {
  3112.     if (np->e_token == ICON && np->e_ival == 0) {
  3113.         return;
  3114.     }
  3115.     error("bad ':' combination");
  3116. }
  3117.  
  3118. mayzero(np)
  3119. NODEP np;
  3120. {
  3121.     if (np->e_token == ICON && np->e_ival == 0) {
  3122.         return 1;
  3123.     }
  3124.     return 0;
  3125. }
  3126.  
  3127. widen(ty)
  3128. {
  3129.     switch (ty) {
  3130.     case K_CHAR:
  3131.     case T_UCHAR:
  3132.         return K_INT;
  3133.     case K_SHORT:
  3134.         return K_INT;
  3135.     case K_FLOAT:
  3136.         return K_DOUBLE;
  3137.     default:
  3138.         return ty;
  3139.     }
  3140. }
  3141.  
  3142. int pri_t[] = {
  3143.     1, 6,        /* uchar, ulong */
  3144.     5,2,4,3,0,    /* long, short, uns, int, char */
  3145.     7,8,9        /* float, double, void */
  3146. };
  3147.  
  3148.  
  3149. extern nmerrors;
  3150.  
  3151. maxt(t1, t2)
  3152. {
  3153.  
  3154.     if (nmerrors)
  3155.         return K_INT;
  3156.     if (pri_t[t1-FIRST_BAS] > pri_t[t2-FIRST_BAS])
  3157.         return t1;
  3158.     return t2;
  3159. }
  3160. SHAR_EOF
  3161. cat << \SHAR_EOF > nodes.c
  3162. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  3163.  *
  3164.  * Permission is granted to anyone to use this software for any purpose
  3165.  * on any computer system, and to redistribute it freely, with the
  3166.  * following restrictions:
  3167.  * 1) No charge may be made other than reasonable charges for reproduction.
  3168.  * 2) Modified versions must be clearly marked as such.
  3169.  * 3) The authors are not responsible for any harmful consequences
  3170.  *    of using this software, even if they result from defects in it.
  3171.  *
  3172.  *    nodes.c
  3173.  *
  3174.  *    Node allocation, deallocation, searching, printing
  3175.  *    and other node handling
  3176.  */
  3177.  
  3178. #include <stdio.h>
  3179. #include "param.h"
  3180. #include "nodes.h"
  3181.  
  3182. extern FILE *output;
  3183. NODE *freelist;
  3184.  
  3185. #define NODEINCR    100
  3186.  
  3187. extern int oflags[];
  3188. #define debug oflags['n'-'a']
  3189.  
  3190. #define NODELEN    (sizeof(NODE)/4)
  3191.  
  3192. int nodesmade, nodesavail;
  3193.  
  3194. NODE *
  3195. allocnode()
  3196. {
  3197.     char *calloc();
  3198.     NODE *t;
  3199.     int i;
  3200.  
  3201. retry:
  3202.     if (freelist != 0) {
  3203.         t = freelist;
  3204.         freelist = t->n_next;
  3205.         lclr(t, NODELEN);
  3206.         nodesavail--;
  3207.         if (debug)
  3208.             printf("%lx+ ", t);
  3209.         return t;
  3210.     }
  3211.     t = (NODE *)calloc(NODEINCR, sizeof(NODE));
  3212.     if (t == 0) {
  3213.         printf("malloc failure\n");
  3214.         exit(1);
  3215.     }
  3216.     nodesmade += NODEINCR;
  3217.     nodesavail += NODEINCR;
  3218.     for (i=0; i<NODEINCR; i++)
  3219.         t[i].n_next = &t[i+1];
  3220.     t[NODEINCR-1].n_next = 0;
  3221.     freelist = t;
  3222.     goto retry;
  3223. }
  3224.  
  3225. freeunit(t)
  3226. NODE *t;
  3227. {
  3228.     if (t->n_flags & N_ISFREE) {
  3229.         printf("%lx ", t);
  3230.         error("Freeing free node");
  3231.         exit(1);
  3232.     } else
  3233.         t->n_flags |= N_ISFREE;
  3234.     t->n_next = freelist;
  3235.     freelist = t;
  3236.     nodesavail++;
  3237.     if (debug)
  3238.         printf("%lx- ", t);
  3239. }
  3240.  
  3241. freenode(t)
  3242. NODE *t;
  3243. {
  3244.     register NODE *nxt;
  3245.  
  3246.     if (t == NULL) return;
  3247. again:
  3248.     if (t->n_right)
  3249.         freenode(t->n_right);
  3250.     if (t->n_nmx)
  3251.         freenode(t->n_nmx);
  3252.     if (t->n_tptr && (t->n_flags & N_COPYT) == 0)
  3253.         freenode(t->n_tptr);
  3254.     nxt = t->n_left;
  3255.     freeunit(t);
  3256.     if (nxt) {
  3257.         t = nxt;
  3258.         goto again;    /* minimize left recursion */
  3259.     }
  3260. }
  3261.  
  3262. put_nnm(t)
  3263. NODE *t;
  3264. {
  3265.     printf("%s", t->n_name);
  3266.     while (t->n_nmx) {
  3267.         t = t->n_nmx;
  3268.         printf("%s", t->n_name);
  3269.     }
  3270. }
  3271.  
  3272. qput_nnm(t, fd)
  3273. NODE *t;
  3274. FILE *fd;
  3275. {
  3276.     fprintf(fd, "%s", t->n_name);
  3277.     while (t->n_nmx) {
  3278.         t = t->n_nmx;
  3279.         fprintf(fd, "%s", t->n_name);
  3280.     }
  3281. }
  3282.  
  3283. fput_nnm(t)
  3284. NODE *t;
  3285. {
  3286.     fprintf(output, "%s", t->n_name);
  3287.     while (t->n_nmx) {
  3288.         t = t->n_nmx;
  3289.         fprintf(output, "%s", t->n_name);
  3290.     }
  3291. }
  3292.  
  3293. /* add a short string (less than NMXSIZE) to front of name */
  3294. nnmins(t, s)
  3295. NODEP t;
  3296. char *s;
  3297. {
  3298.     register i, j;
  3299.     char tbuf[NMSIZE];
  3300.     NODEP n;
  3301.  
  3302.     i = strlen(t->n_name);
  3303.     j = strlen(s);
  3304.     if (j > NMSIZE-1)
  3305.         return;        /* compiler error */
  3306.     if (i+j <= NMSIZE-1) {        /* fits in node */
  3307.         strcpy(tbuf, t->n_name);
  3308.         strcpy(t->n_name, s);
  3309.         strcpy(t->n_name+j, tbuf);
  3310.     } else {
  3311.         n = allocnode();
  3312.         n->n_nmx = t->n_nmx;
  3313.         t->n_nmx = n;
  3314.         strcpy(n->n_name, t->n_name);
  3315.         strcpy(t->n_name, s);
  3316.     }
  3317. }
  3318.  
  3319. /* add a short string (less than NMXSIZE) to end of name */
  3320. nnmadd(t, s)
  3321. NODE *t;
  3322. char *s;
  3323. {
  3324.     register i,j;
  3325.     int sizeb;
  3326.     NODEP n;
  3327.  
  3328.     /* find last node */
  3329.     sizeb = NMSIZE;
  3330.     while (t->n_nmx) {
  3331.         t = t->n_nmx;
  3332.         sizeb = NMXSIZE;
  3333.     }
  3334.     /* fits in current last node? */
  3335.     i = strlen(s);
  3336.     j = strlen(t->n_name);
  3337.     if (i < sizeb-j) {
  3338.         strcat(t->n_name, s);
  3339.         return;
  3340.     }
  3341.     /* put all of s in new node */
  3342.     n = allocnode();
  3343.     t->n_nmx = n;
  3344.     t = n;
  3345.     strncpy(t->n_name, s, NMXSIZE-1);
  3346.     t->n_name[NMXSIZE-1] = 0;
  3347. }
  3348.  
  3349. nscpy(t, s)
  3350. NODE *t;
  3351. char *s;
  3352. {
  3353.     register i;
  3354.     NODEP n;
  3355.  
  3356.     i = strlen(s);
  3357.     strncpy(t->n_name, s, NMSIZE-1);
  3358.     t->n_name[NMSIZE-1] = 0;
  3359.     i -= NMSIZE-1;
  3360.     s += NMSIZE-1;
  3361.     while (i > 0) {
  3362.         n = allocnode();
  3363.         t->n_nmx = n;
  3364.         t = n;
  3365.         strncpy(t->n_name, s, NMXSIZE-1);
  3366.         t->n_name[NMXSIZE-1] = 0;
  3367.         i -= NMXSIZE-1;
  3368.         s += NMXSIZE-1;
  3369.     }
  3370. }
  3371.  
  3372. putlist(head, np)
  3373. NODE **head, *np;
  3374. {
  3375.     np->n_next = *head;
  3376.     *head = np;
  3377. }
  3378.  
  3379. puthlist(head, np)
  3380. NODE *head[], *np;
  3381. {
  3382.     putlist(&head[hash(np->n_name)], np);
  3383. }
  3384.  
  3385. NODE *
  3386. llook(head, np)
  3387. NODE *head, *np;
  3388. {
  3389.     register NODEP p;
  3390.  
  3391.     for (p=head; p != NULL; p = p->n_next)
  3392.         if (xstrcmp(p, np) == 0) {
  3393.             return p;
  3394.         }
  3395.     return NULL;
  3396. }
  3397.  
  3398. NODE *
  3399. hlook(head, np)
  3400. NODE *head[], *np;
  3401. {
  3402.     register NODEP p;
  3403.  
  3404.     p = head[hash(np->n_name)];
  3405.     return llook(p, np);
  3406. }
  3407.  
  3408. hash(s)
  3409. register char *s;
  3410. {
  3411.     register hval;
  3412.  
  3413.     hval = 0;
  3414.     while (*s)
  3415.         hval += *s++;
  3416.     return hval & (NHASH-1);
  3417. }
  3418.  
  3419. xstrcmp(p1, p2)
  3420. NODE *p1, *p2;
  3421. {
  3422.     int rv;
  3423.  
  3424.     if ((rv = strcmp(p1->n_name, p2->n_name)) != 0)
  3425.         return rv;
  3426.     if (p1->n_nmx == NULL) {
  3427.         if (p2->n_nmx == NULL)
  3428.             return 0;
  3429.         return -1;
  3430.     }
  3431.     if (p2->n_nmx == NULL)
  3432.         return 1;
  3433.     return xstrcmp(p1->n_nmx, p2->n_nmx);
  3434. }
  3435.  
  3436. char *
  3437. scopy(s)
  3438. char *s;
  3439. {
  3440.     int i;
  3441.     char *p;
  3442.  
  3443.     i = strlen(s)+1;
  3444.     if (i > sizeof(NODE)) {
  3445.         error("preproc name too big");
  3446.         i = sizeof(NODE);
  3447.         s[i-1] = 0;
  3448.     }
  3449.     p = (char *)allocnode();
  3450.     strcpy(p, s);
  3451.     return p;
  3452. }
  3453.  
  3454. sfree(s)
  3455. char *s;
  3456. {
  3457.     NODEP np;
  3458.  
  3459.     np = (NODEP)s;
  3460.     np->n_flags = 0;
  3461.     freeunit(np);
  3462. }
  3463.  
  3464. printlist(np)
  3465. NODE *np;
  3466. {
  3467.     putchar('\n');
  3468.     prln(np, 2);
  3469. }
  3470.  
  3471. prln(np, indent)
  3472. NODE *np;
  3473. {
  3474.     register NODE *svl, *nxtl;
  3475.  
  3476.     for (svl=np; svl != NULL; svl = nxtl) {
  3477.         nxtl = svl->n_next;
  3478.         svl->n_next = NULL;
  3479.         prnode(svl,indent);
  3480.         svl->n_next = nxtl;
  3481.         /* special hack for tag list */
  3482.         if ((svl->n_flags & N_BRKPR) && svl->n_right)
  3483.             prln(svl->n_right, indent+2);
  3484.     }
  3485. }
  3486.  
  3487. codeprint(np)
  3488. NODEP np;
  3489. {
  3490.     putchar('\n');
  3491.     cprnode(np,0);
  3492. }
  3493.  
  3494. cprnode(np,indent)
  3495. NODE *np;
  3496. {
  3497.     int ni;
  3498.     NODEP tp;
  3499.  
  3500.     ni = indent+1;
  3501.     while (indent--)
  3502.         putchar(' ');
  3503.     if (np == NULL) {
  3504.         printf("<NULL>\n");
  3505.         return;
  3506.     }
  3507.     put_nnm(np);    /* Note: BRKPR doesnt break long names */
  3508.     if (np->g_offs)
  3509.         printf(" o%ld ", np->g_offs);
  3510.     if (np->g_rno)
  3511.         printf(" r%d ", np->g_rno);
  3512.     if (np->g_needs)
  3513.         printf(" n%x ", np->g_needs);
  3514.     if (debug) {
  3515.         printf("@%lx ", np);
  3516.         if (np->n_flags & N_COPYT)
  3517.             printf("C ");
  3518.         if (np->n_flags & N_BRKPR)
  3519.             printf("B ");
  3520.     }
  3521.     if (np->n_flags & N_BRKPR) {
  3522.         putchar('\n');
  3523.         return;
  3524.     }
  3525.     if (np->g_betw)
  3526.         printf(" {%s}", np->g_betw);
  3527.     if (np->g_code) {
  3528.         if (np->n_flags & N_COPYT)
  3529.             printf(" <%s>", np->g_code);
  3530.         else
  3531.             for (tp=np->g_code; tp; tp = tp->g_code)
  3532.                 printf(" <%s>", tp->n_name);
  3533.     }
  3534.     putchar(' ');
  3535.     out_a(np, stdout);
  3536.     putchar('\n');
  3537.     if (np->n_left) {
  3538.         cprnode(np->n_left,ni);
  3539.     } else if (np->n_right)
  3540.         cprnode(NULL, ni);
  3541.     if (np->n_right) {
  3542.         cprnode(np->n_right,ni);
  3543.     }
  3544. }
  3545.  
  3546. printnode(np)
  3547. NODE *np;
  3548. {
  3549.     putchar('\n');
  3550.     prnode(np,0);
  3551. }
  3552.  
  3553. prnode(np,indent)
  3554. NODE *np;
  3555. {
  3556.     int ni;
  3557.  
  3558.     ni = indent+1;
  3559.     while (indent--)
  3560.         putchar(' ');
  3561.     if (np == NULL) {
  3562.         printf("<NULL>\n");
  3563.         return;
  3564.     }
  3565.     put_nnm(np);    /* Note: BRKPR doesnt break long names */
  3566.     if (np->e_offs)
  3567.         printf(" o%ld ", np->e_offs);
  3568.     if (np->e_rno)
  3569.         printf(" r%d ", np->e_rno);
  3570.     if (np->e_fldw)
  3571.         printf(" (%d,%d) ", np->e_fldw, np->e_fldo);
  3572.     if (debug) {
  3573.         printf("@%lx ", np);
  3574.         if (np->n_flags & N_COPYT)
  3575.             printf("C ");
  3576.         if (np->n_flags & N_BRKPR)
  3577.             printf("B ");
  3578.     }
  3579.     if (np->n_flags & N_BRKPR) {
  3580.         putchar('\n');
  3581.         return;
  3582.     }
  3583.     if (np->n_tptr) {
  3584.         if (np->e_flags & 256)    /* IMMEDID */
  3585.             printf(" $$$ ");
  3586.         tprint(np->n_tptr);
  3587.     }
  3588.     putchar('\n');
  3589.     if (np->n_left) {
  3590.         prnode(np->n_left,ni);
  3591.     } else if (np->n_right)
  3592.         prnode(NULL, ni);
  3593.     if (np->n_right) {
  3594.         prnode(np->n_right,ni);
  3595.     }
  3596. }
  3597.  
  3598. tprint(np)
  3599. NODEP np;
  3600. {
  3601.     while (np != NULL) {
  3602.         putchar(' ');
  3603.         put_nnm(np);
  3604. #ifdef HANS
  3605.         if (np->t_size)
  3606.             printf(" s%ld", np->t_size);
  3607.         if (np->t_aln)
  3608.             printf(" a%d", np->t_aln);
  3609. #endif
  3610.         if (debug)
  3611.             printf("@%lx", np);
  3612.         np = np->n_tptr;
  3613.     }
  3614. }
  3615.  
  3616. NODEP
  3617. copynode(op)
  3618. NODEP op;
  3619. {
  3620.     NODEP np;
  3621.  
  3622.     if (op == NULL) return NULL;
  3623.     np = allocnode();
  3624.     lcpy(np, op, NODELEN);
  3625.     if (np->n_nmx)
  3626.         np->n_nmx = copynode(np->n_nmx);
  3627.     if (np->n_right)
  3628.         np->n_right = copynode(np->n_right);
  3629.     if (np->n_left)
  3630.         np->n_left = copynode(np->n_left);
  3631.     if (np->n_tptr)
  3632.         np->n_flags |= N_COPYT;
  3633.     return np;
  3634. }
  3635.  
  3636. NODEP
  3637. copyone(op)
  3638. NODEP op;
  3639. {
  3640.     NODEP np;
  3641.  
  3642.     if (op == NULL) return NULL;
  3643.     np = allocnode();
  3644.     lcpy(np, op, NODELEN);
  3645.     if (np->n_nmx)
  3646.         np->n_nmx = copyone(np->n_nmx);
  3647.     if (np->n_right)
  3648.         np->n_right = NULL;
  3649.     if (np->n_left)
  3650.         np->n_left = NULL;
  3651.     if (np->n_tptr)
  3652.         np->n_flags |= N_COPYT;
  3653.     return np;
  3654. }
  3655.  
  3656. NODEP
  3657. copy_nol(op)
  3658. NODEP op;
  3659. {
  3660.     NODEP np;
  3661.  
  3662.     if (op == NULL) return NULL;
  3663.     np = allocnode();
  3664.     lcpy(np, op, NODELEN);
  3665.     if (np->n_nmx)
  3666.         np->n_nmx = copynode(np->n_nmx);
  3667.     if (np->n_right) /* break right links */
  3668.         np->n_right = NULL;
  3669.     if (np->n_tptr)
  3670.         np->n_flags |= N_COPYT;
  3671.     return np;
  3672. }
  3673.  
  3674. NODEP
  3675. copylist(np, tailp)
  3676. NODE *np, **tailp;
  3677. {
  3678.     NODEP rv, nx;
  3679.     register NODEP tail;
  3680.  
  3681.     if (np == NULL) {
  3682.         *tailp = NULL;
  3683.         return NULL;
  3684.     }
  3685.     rv = copy_nol(np);
  3686.     tail = rv;
  3687.     while (tail->n_left) {
  3688.         nx = copy_nol(tail->n_left);
  3689.         tail->n_left = nx;
  3690.         tail = nx;
  3691.     }
  3692.     *tailp = tail;
  3693.     return rv;
  3694. }
  3695.  
  3696. NODE *
  3697. nthnode(np, n)
  3698. NODE *np;
  3699. {
  3700.     while (n--)
  3701.         if (np == NULL)
  3702.             return NULL;
  3703.         else
  3704.             np=np->n_next;
  3705.     return np;
  3706. }
  3707.  
  3708. NODE *
  3709. rthnode(np, n)
  3710. NODE *np;
  3711. {
  3712.     while (n--)
  3713.         if (np == NULL)
  3714.             return NULL;
  3715.         else
  3716.             np=np->n_right;
  3717.     return np;
  3718. }
  3719. SHAR_EOF
  3720. #    End of shell archive
  3721. exit 0
  3722. -- 
  3723. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  3724. Have five nice days.
  3725.